I am using some 3rd party library that exposes some type (returned by a method).
This type has some protected fields i am interested in, however i am not able to use them since their visibility is protected.
Here is a simplification of the problem:
public class A
{
protected object Something;
public A Load()
{
return new A();
}
}
public class ExtendedA : A
{
public void DoSomething()
{
// Get an instance.
var a = Load();
// Access protected fields (doesn't compile).
a.Something = ....
}
}
Is there any easy way to achieve this?
Description
You can access the Field using this.Something because your class is derived from class A.
If you want to create a instance of the class A, not your derived class, you can only access the field using reflection.
Sample using Reflection
public class ExtendedA : A
{
public void DoSomething()
{
// Get an instance.
var a = Load();
//get the type of the class
Type type = a.GetType();
BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
// get the field info
FieldInfo finfo = type.GetField("Something", bindingFlags);
// set the value
finfo.SetValue(a, "Hello World!");
// get the value
object someThingField = finfo.GetValue(a);
}
}
More Information
Accessing Protected Properties and Fields with Reflection
That's because you actually can't access it.
You can't call protected methods on any instance other than this (or base).
Just because your code happens to be in a descendant of A does not mean that this rule suddenly changes.
Eric Lippert has an excellent explanation in his blog:
http://blogs.msdn.com/b/ericlippert/archive/2005/11/09/why-can-t-i-access-a-protected-member-from-a-derived-class.aspx
By inheriting from A you create a new class (ExtendedA) which has a member Something that you can access from within ExtendedA
public class ExtendedA : A
{
public void DoSomething()
{
// works fine
this.Something = ....
}
}
Inheriting does not give you the ability to reach into an instance of A to change Something
public class ExtendedA : A
{
public void DoSomething()
{
var a = new A();
// access level error
a.Something = ....
}
}
If you want to use the Something value you can do so within ExtendedA but only on the ExtendedA instance's own copy of Something.
hth,
Alan.
Related
I am building some integration tests for my database stored procedures.
I have setup an xUnit project and implemented Fixture pattern. To show you:
public class MyTableTest : IClassFixture<DatabaseFixture>
{
public MyTableTest()
{
//DO SOMETHING
}
[Fact]
public void Test()
{
//DO SOMETHING
}
}
And:
public class DatabaseFixture : IDisposable
{
public void Dispose()
{
// ... clean up test data from the database ...
}
}
This DatabaseFixture is something that will be shared among all of my test classes. Why? Because I want some common logic happening at the end of every test, such as cleanup.
Point is that I need to know which table to clean, which in my example would be MyTable. Such information I would retrieve by using reflection when the Dispose method will run against the instance of MyTableTest being disposed . How can I achieve this? Is it even possible (and correct) trying to achieve this? Thanks in advance.
You can have a TableName property in the DatabaseFixture class. Then receive an instance of the class in constructor of your test classes and set that TableName property. Later you can use it in dispose to do some cleanup.
public class MyTableTest : IClassFixture<DatabaseFixture>
{
DatabaseFixture databaseFixture;
public MyTableTest(DatabaseFixture databaseFixture)
{
this.databaseFixture = databaseFixture;
databaseFixture.TableName = "MyTable";
}
[Fact]
public void Test()
{
}
}
public class DatabaseFixture : IDisposable
{
//...
public string TableName { get; set; }
//...
public void Dispose()
{
// Cleanup based on TableName
}
}
To learn more about sharing context in xUnit, take a look at:
Shared Context between Tests
Comparing xUnit.net to other frameworks
You can use custom attributes to attach any arbitrary data to your derived Fixture class.
For example
you can create a TableNameAttribute like this:
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class TableNameAttribute : Attribute
{
public string Name { get; }
public TableNameAttribute(string name)
{
this.Name = name;
}
}
you can apply this attribute to your derived fixture class:
[TableName("MyTable")]
public class MyTableFixture : DatabaseFixture { }
you can use that fixture class inside your test
public class MyTableTest : IClassFixture<MyTableFixture>
{
[Fact]
public void Test()
{
//DO SOMETHING
}
}
Finally this is how you can retrieve the Name from the Dispose method:
public abstract class DatabaseFixture : IDisposable
{
...
public void Dispose()
{
var attribute = this.GetType().GetCustomAttribute(typeof(TableNameAttribute));
if (attribute is TableNameAttribute tableNameAttr)
Console.WriteLine(tableNameAttr.Name);
}
}
Is it even possible (and correct) trying to achieve this?
No. Reflection cannot tell type T in what context T is used; reflection only sees T's declaration.
More specific to your situation, reflection cannot tell type DatabaseFixture that it is being used as a type parameter of generic interface IClassFixture in the declaration of MyTableTest. In other words, for this set of declarations,
class A { }
class B <T> { }
class C : B<A> { }
A cannot reflectively determine that it is used in C's declaration, but C can know about its usage of A:
typeof(C)
.BaseType // B
.GetGenericArguments()[0] // A
How can I achieve this?
Depending on how you are using DatabaseFixture, you could get the calling test class using the StackTrace (if you are really bent on using reflection). Here is a simple example:
public class DisposableObject : System.IDisposable
{
public void Dispose()
{
var stack = new System.Diagnostics.StackTrace();
// This will log the name of the class that instantiated and disposed this.
System.Console.WriteLine(stack.GetFrame(1).GetMethod().DeclaringType.Name);
return;
}
}
If your DatabaseFixture is not called directly from your test class, you will either have to know the offset to pass to GetFrame(int), or you will need to search each frame until you find the first DeclaringType that matches your requirements (e.g., BaseType is IClassFixture with Generic Argument DatabaseFixture), something like this:
System.Type testClassType = new StackTrace()
.GetFrames()
.Where(f =>
{
System.Type baseType = f.GetMethod().DeclaringType.BaseType;
return typeof(IClassFixture<DatabaseFixture>).IsAssignableFrom(baseType);
})
.FirstOrDefault() // First matching result (assuming you found any)
?.GetMethod() // Get the reflected Method
.DeclaringType; // Get the type (e.g. class) that declares this method.
string tableName = testClassType.Name.Replace("Test", "");
Otherwise, you will need to set the table name manually, as suggested by Reza and Peter.
I need help parsing specific methods from classes derived from a base class and add them to a delegate collection.
I have a bunch of classes that are derives from a single base class. Each of those classes have 1 or more methods with a specific custom attribute [IntentHandler]. Those methods all have a single parameter. The parameter type is different depending on the method, but each method's parameter is derived from another base class (public class Intent). I need to find all those methods, create an appropriate delegate and add them to a delegate "Dictionary" where the key is the parameter's type, and the value is the method.
Right now, I have each subclass creating and registering it's method delegate, but there are a LOT of sub classes, each requiring the code to register it's methods. I would rather handle this through the base class using System.Reflection I believe. It would greatly reduce code and allow for better expansion later.
public class StaticService : Service
{
delegate void ObjectCreatedIntentHandler(ObjectCreatedIntent oci);
private ObjectCreatedIntentHandler handleObjectCreatedIntent;
public StaticService()
{
handleObjectCreatedIntent = HandleObjectCreatedIntent;
}
private void HandleObjectCreatedIntent(ObjectCreatedIntent oci)
{
}
internal override void RegisterIntentHandlers(IntentManager registry)
{
registry.RegisterForIntent(typeof(ObjectCreatedIntent), handleObjectCreatedIntent);
}
internal override void UnregisterIntentHandlers(IntentManager registry)
{
registry.UnregisterForIntent(typeof(ObjectCreatedIntent), handleObjectCreatedIntent);
}
}
I would prefer something more along the lines of:
public class StaticService : Service
{
public StaticService()
{
}
[IntentHandler]
private void HandleObjectCreatedIntent(ObjectCreatedIntent oci)
{
}
}
and the base class
public class Service
{
public Service()
{
RegisterIntents()
}
private void RegisterIntents()
{
// Find all classes derived from Service
// Find each method in those classes with the [IntentHandler]
// Attribute
// Get the method's Intent Class derived parameter type
// create a delegate I can invoke later for that method.
// Add the delegate to a Dictionary<Intent,Delegate>;
}
}
I think I found a solution. I am using Action now instead of a Delegate.
In my base class, I am now doing this:
internal void RegisterIntentHandlers(IntentManager registry)
{
RegisterIntentHandlers(this.GetType(), registry);
}
internal void RegisterIntentHandlers(Type klass, IntentManager registry)
{
foreach (System.Reflection.MethodInfo m in klass.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
{
foreach (Attribute attribute in m.GetCustomAttributes())
{
if (attribute is IntentHandler)
{
if (m.GetParameters().Count() == 1)
{
ParameterInfo p = m.GetParameters()[0];
Type paramClass = p.ParameterType;
if (paramClass.IsAssignableFrom(typeof(Intent)))
{
object consumerKey = this.GetType().FullName + "#" + m.Name;
Action<Intent> intentConsumer = (Action<Intent>)m.CreateDelegate(typeof(Action<Intent>), this);
registry.RegisterForIntent<Intent>(paramClass, consumerKey, intentConsumer);
if (!registration.ContainsKey(paramClass))
registration[paramClass].Add(consumerKey);
}
}
}
}
}
}
I haven't finished testing yet, but it looks right to me. I have to go cleanup all the subclasses now before I can finish testing.
Any opinions/suggestions?
I am trying to dynamically instantiate classes descendant of an abstract class, but the activator is forcing me to override the constructor to every descendant. Is there a way to avoid this?
P.S: I need to pass the parameters in the constructor, only there it can be Write, otherwise, it will always be read!
Is there a way to avoid this?
Short answer: Yes, when you define no constructor in your derived class, the (abstract) base class constructors are used. When you define one, you have to redefine all constructors.
Not without a workaround pattern.
EDIT: Sorry, I'm wrong that does only work for parameterless constructors.
How you can achive your goal,
is using a protected parameterless constructor and a static Create method:
public abstract class Duck {
private string _DucksParam0;
public string DucksParam0 {
get {
return _DucksParam0;
}
}
// Using protected, this constructor can only be used within the class instance
// or a within a derived class, also in static methods
protected Duck() { }
public static DuckT Create<DuckT>(string param0)
where DuckT : Duck
{
// Use the (implicit) parameterless constructor
DuckT theDuck = (DuckT)Activator.CreateInstance(typeof(DuckT));
// This is now your "real" constructor
theDuck._DucksParam0 = param0;
return theDuck;
}
}
public class Donald : Duck {
}
Usage (dotnetfiddle):
public class Program
{
public void Main()
{
Duck d = Duck.Create<Donald>("Hello World");
Console.WriteLine(d.DucksParam0);
}
}
Constructors are not inherited, so if you must instantiate a child object through a constructor with those parameters, then you need to write a new constructor in the child class that basically does base(p1, p2, ..., pn).
Looking at your code, seems that your constructors only assign/initialize fields, so there is no reason why you can't do that somewhere outside the constructor, as long as you control it appropriately. This might be a long shot, but I feel this is more what you want:
public abstract class Parent
{
protected bool foo
{
get;
private set; // just set the property setter as private
}
protected Parent() {
// protected so all instances are created through createAnotherX
// note that nothing is initialized here!
}
public abstract int Enter(); // To override in child classes
// Option 1: use generics
public static T createAnother1<T>(bool f) where T : Parent, new()
{
T p = new T();
p.foo = f;
return p;
}
// Option 2: use the runtime type
public static Parent createAnother2(Type t, bool f)
{
Parent p = Activator.CreateInstance(t) as Parent;
p.foo = f;
return p;
}
// Examples
public static void Main()
{
Parent p1 = Parent.createAnother1<Child>(true);
Parent p2 = Parent.createAnother2(typeof(Child), true);
}
}
// the child class only has to worry about overriding Enter()
public class Child : Parent
{
public override int Enter()
{
return 1;
}
}
Note that you must instantiate objects through the createAnotherX because the default constructor is protected. In addition, as per your comment, see that the property is defined so that only you can set values, which is what you tried to do in your code when explicitly ignoring the setter.
Ok, edited the code for clarification:
Question: How can I access the attribute [MyAttr("...")] in TestClassOne/Two from BaseClass.TheAttribute...?
All classes except TestClassOne/Two will be compiled in to my "core" and delivered as a dev-platform to a customer.
The TestClassOne/Two is developed by the customer, so there can be no knowledge of the TestClassOne/Two in the "core".
Code below is compiled into "core" and delivered to customer as dll.
[TestMethod()]
public void AttrTest()
{
var one = new TestClassOne();
var attrOne = one.MyTestProperty.TheAttribute;
var two = new TestClassTwo();
var attrTwo = two.MyTestProperty.TheAttribute;
}
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
}
public class BaseClass
{
public string TheAttribute
{
get {
// Here I would like to get the "[MyAttr("...")]" from the classes in the bottom
return null;
}
}
}
public class SubClass : BaseClass
{
}
Code below is developed by customer (using my dll's)
public class TestClassOne
{
[MyAttr("Attribute one")]
public SubClass MyTestProperty = new SubClass();
}
public class TestClassTwo
{
[MyAttr("Attribute two")]
public SubClass MyTestProperty = new SubClass();
}
You can get directly from type Test:
var result = typeof (Test)
.GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
.GetCustomAttribute<MyAttr>();
Edit 3:
You can walk the call stack, looking for a relevant attribute in a relevant member in a relevant class. Try this:
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
public string getAttr()
{
return _test;
}
}
public class BaseClass
{
private string theString;
public BaseClass()
{
StackTrace callStack = new StackTrace();
for ( int i = 0; i < callStack.FrameCount; i++ )
{
Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
{
foreach ( var z in m.GetCustomAttributes(typeof(MyAttr)) )
{
MyAttr theAttr = z as MyAttr;
if ( z!= null )
{
theString = z.getAttr();
return;
}
}
}
}
}
public string Test
{
get {
return theString;
}
}
}
This requires that your customer always initializes the SubClass member inside the class that declares it. If they start deriving TestClassOne or have it and TestClassTwo derive from a common class that initializes the member, this code will break.
With clever use of reflection, you can expand the above code to cover more use cases, but that's beyond the scope of this question.
Edit 2:
No. I'm sorry, but what you're trying to do isn't possible. There's no "normal" way for an instance of SubClass to know if it's being declared in a member field of some other object, or in an element in an array or in a temporary variable in the stack, or whatever. As such, there's no way for that instance to access the attributes of the member field that's declaring it.
(I suppose you might want to try to access the garbage collector to find out where in memory the this object lives, but that's probably way beyond the scope of this problem, and in any case, not something I know how to do.)
I suspect your problem lies elsewhere entirely. Maybe you need to require your customer to make TestClassOne and TestClassTwo derive from a common abstract class. Maybe they need to derive from BaseClass themselves. Maybe you need to add parameters to the constructor. Maybe you need to provide a different interface altogether. We can't know unless you provide more information on your specific business requirements.
Edit:
To access the attributes declared on the MyTest member, try something along these lines:
public class BaseClass
{
public string Test
{
get {
var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
return null;
}
}
}
This will search class Test for a member with the same type as this and look for attributes on that member.
(I don't have my Visual Studio here, to check the exact Where syntax, but it should be pretty close to that...)
Original Answer:
Your attribute is declared on the MyTest member of class Test. But, you're doing GetCustomAttributes on class SubClass itself.
Try this:
[MyAttr("apa")]
public class SubClass : BaseClass
{
}
public class Test
{
public SubClass MyTest = new SubClass();
}
Should get you what you want.
I have a structure which looks basicly like this:
abstract class A
{
protected string Identificator { get; set; }
private void DoSomething()
{
// ...
DoSomethingSpecific();
}
protected abstract void DoSomethingSpecific();
}
Because of the complexity I need do unit tests the DoSomething method to be sure it works allways in the same way. Thats why I created following stub.
public class AStub : A
{
protected override void DoSomethingSpecific()
{
// nothing to do
}
}
I use the PrivateObject class to access the methods and properties of class A be instantiating class AStub. This worked for a while and for some reason crashes now whenever I try to access either the property or the method.
following code for testing:
var sut = new CommonIodAdapterImpl();
var accessor = new PrivateObject(sut);
accessor.SetProperty("Identificator", "blablub");
accessor.Invoke("DoSomething", null);
// assert...
The exception which is thrown is a MissingMethodException telling me that the propertie or method was not found. But when I debug and check the hierachy every seems to be right inclduing the spelling.
Thank you for your help.
You need to set the PrivateType argument to your base class to access the private members at that level.
var accessor = new PrivateObject(sut, new PrivateType(typeof(A)));
Shouldn't that be "public class AStub : A"?
To resolve the missing method exception just compile everything(!) once more. Either you get some compiler error telling you what's wrong or the error will vanish.
If it still doesn't work, check if you don't have multiple copies of the assemblies (including GAC!) and watch in the Deboug-Out-Window if it loads the assemblies from the correct path.
I just tried something similar, i assmued it's because the property is protected rather than private.
I created my own accessor in my test assembly
public class AAccessor : A
{
// use this instead of Identificator
public string IdentificatorAccessor
{
get { return this.Identificator; }
set { this.Identificator = value; }
}
// test this method in your unit test
public void DoSomethingAccessor()
{
this.DoSomethingSpecific()
}
// need this to satisfy the abstract class
protected override void DoSomethingSpecific()
{
// do nothing here
}
}
public class BaseClass
{
private int _fieldToSet;
...
}
public class DerivedClass : BaseClass
{
...
}
// Unit Test Code
public void Test()
{
DerivedClass d = new DerivedClass();
PrivateObject privObj = new PrivateObject(d, new PrivateType(typeof(BaseClass));
privObj.SetFieldOrProperty("fieldToSet", 8675309);
...
}