How to Access a descendant object's internal method in C#
-
I'm trying to access a method that is marked as internal in the parent class (in its own assembly) in an object that inherits from the same parent. Let me explain what I'm trying to do... I want to create Service classes that return IEnumberable with an underlying List to non-Service classes (e.g. the UI) and optionally return an IEnumerable with an underlying IQueryable to other services. I wrote some sample code to demonstrate what I'm trying to accomplish, shown below. The example is not real life, so please remember that when commenting. All services would inherit from something like this (only relevant code shown): public class ServiceBase<T> { protected readonly ObjectContext _context; protected string _setName = String.Empty; public ServiceBase(ObjectContext context) { _context = context; } public IEnumerable<T> GetAll() { return GetAll(false); } //These are not the correct access modifiers.. I want something //that is accessible to children classes AND between descendant classes internal protected IEnumerable<T> GetAll(bool returnQueryable) { var query = _context.CreateQuery<T>(GetSetName()); if(returnQueryable) { return query; } else { return query.ToList(); } } private string GetSetName() { //Some code... return _setName; } } Inherited services would look like this: public class EmployeeService : ServiceBase<Employees> { public EmployeeService(ObjectContext context) : base(context) { } } public class DepartmentService : ServiceBase<Departments> { private readonly EmployeeService _employeeService; public DepartmentService(ObjectContext context, EmployeeService employeeService) : base(context) { _employeeService = employeeService; } public IList<Departments> DoSomethingWithEmployees(string lastName) { //won't work because method with this signature is not visible to this class var emps = _employeeService.GetAll(true); //more code... } } Because the parent class lives is reusable, it would live in a different assembly than the child services. With GetAll(bool returnQueryable) being marked internal, the children would not be able to see each other's GetAll(bool) method, just the public GetAll() method. I know that I can add a new internal GetAll method to each service (or perhaps an intermediary parent class within the same assembly) so that each child service within the assembly can see each other's method; but it seems unnecessary since the functionality is already available in the parent class. For example: internal IEnumerable<Employees> GetAll(bool returnIQueryable) { return base.GetAll(returnIQueryable); } Essentially what I want is for services to be able to access other service methods as IQueryable so that they can further refine the uncommitted results, while everyone else gets plain old lists. Any ideas? EDIT You know what, I had some fun playing a little code golf with this... but ultimately I wouldn't be able to use this scheme anyway because I pass interfaces around, not classes. So in my example GetAll(bool returnIQueryable) would not be in the interface, meaning I'd have to do casting, which goes against what I'm trying to accomplish. I'm not sure if I had a brain fart or if I was just too excited trying to get something that I thought was neat to work. Either way, thanks for the responses.
-
Answer:
What's wrong with the obvious answer of making the method public? Accessibility is not secure anyway, so "evil people" could use reflection to bypass whatever modifier you put on. And since you want to call these methods from unrelated "sibling" classes they should be public, as there is no "sibling" accessibility modifier. Alternative suggestion: Apply the [assembly:InternalsVisibleTo("SomeOtherAssembly")] attribute to grant other business domain assemblies access to the internal members. Note that this adds a maintenance burden (if you rename or add assemblies), uses "magic strings", and negates the original meaning of internal (since all internal members now will be visible to these other assemblies as well).
Giovanni Galbo at Stack Overflow Visit the source
Other answers
When your descendant classes would live in the same assembly, this would be easier. However, the following 'trick' also works when your classes live in separate assemblies (changing the interface's internal keyword to public), but it would only prevent the method from being called when the object is not cast. For example, casting an InheritedClass object to an IBaseInterface would allow anyone to call the GetValue method. This is something you can't really prevent, because even if there where some combination of keywords which could do what you want, someone could still call the methods through reflection. internal interface IBaseInterface { string GetValue(); } public abstract class MyBase : IBaseInterface { string IBaseInterface.GetValue() { return "MyBase"; } } public class InheritedClass : MyBase { public void PrintValue(IBaseInterface someclass) { Console.WriteLine(someclass.GetValue()); } }
Virtlink
Perhaps I am missing something, but you should be able to mark it as protected internal and accomplish your goals. namespace Foo { class A { protected internal void D() { Console.WriteLine(this.ToString() + " says 'Blah'"); } } } namespace Bar { class B : Foo.A { public B() { } } } namespace Baz { class C : Foo.A { public C() { D(); Bar.B b = new Bar.B(); b.D(); Foo.A a = new Foo.A(); a.D(); } } } To see the output Baz.C c = new Baz.C(); This is all legal code. Foo.A is the base, Bar.B and Baz.C inherit from Foo.A. void D is a protected internal member of A. Baz.C can invoke D() as expected, as well as create instances of Bar.B and Foo.A and invoke their D() methods as well. protected internal members are visible to all descendant classes in any assembly and all classes within the same assembly as the base. The accessibility ends outside of those bounds. Non-descendant classes within the same assemblies as the the children would not be able to see the member.
Anthony Pegram
Related Q & A:
- How To Send a Complex Object to a Rest Web Service?Best solution by codeproject.com
- How to access a non static method in an abstract class's static method?Best solution by Stack Overflow
- How to get a specific data after post method?Best solution by Stack Overflow
- How to pass a javascript object back to the server?Best solution by developer.mozilla.org
- How to create a flexible object?
Just Added Q & A:
- How many active mobile subscribers are there in China?Best solution by Quora
- How to find the right vacation?Best solution by bookit.com
- How To Make Your Own Primer?Best solution by thekrazycouponlady.com
- How do you get the domain & range?Best solution by ChaCha
- How do you open pop up blockers?Best solution by Yahoo! Answers
For every problem there is a solution! Proved by Solucija.
-
Got an issue and looking for advice?
-
Ask Solucija to search every corner of the Web for help.
-
Get workable solutions and helpful tips in a moment.
Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.