How to call Method of Private Property using Reflection in c#? - c#

I have some problems with my project.
I want to call one method from private Property like private clsBUS_DEMO prop_DEMO
clsBUS_DEMO has a Method, which Name is public void SayHello().
This is my code
PropertyInfo p = this.GetType().GetProperty("SayHello");
p is null because program can't find prop_DEMO
Can anybody help me about this?

clsBUS_DEMO prop_DEMO is not a property, it's a Field. You need to use GetFields to get it and also since it's private you need to pass BindingFlags.NonPublic and BindingFlags.Instance.
Here is a sample of how you should do it
static void Main(string[] args)
{
Bar bar = new Bar();
Foo foo = (Foo)bar.GetType().GetField("a", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(bar);
foo.GetType().GetMethod("ShowMessage").Invoke(foo,new object[] { });
}
public class Bar
{
private Foo a;
public Bar()
{
a = new Foo();
}
}
public class Foo
{
public void ShowMessage()
{
Console.WriteLine("Hello World!");
}
}

Okay guys!
I'm done :)
I just Create Property get{} set{} and use this code :D
PropertyInfo p = this.GetType().GetProperty("LoaiSP_BUS", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
Thanks all!

Call a method of private property? Not sure if I understood what you want, it would be useful to have the class that represent you object. Do you mean call a property that returns an object and then call a method of that object?
Anyways, I think there's a lot information out there about that topic, for example:
How do I use reflection to invoke a private method?
Find a private field with Reflection?
class MyClass1
{
public MyClass1()
{
Prop = new MyClass2();
}
public MyClass2 Prop { get; set; }
}
class MyClass2
{
private int Test()
{
return 5;
}
}
static void Main(string[] args)
{
var obj = new MyClass1();
var obj2 = obj.Prop;
var propInfo = obj.GetType().GetProperty("Prop");
var obj2Reflection = propInfo.GetValue(obj, null);
var dynMethod = obj2.GetType().GetMethod("Test", BindingFlags.NonPublic | BindingFlags.Instance);
var obj2Return = dynMethod.Invoke(obj2, null);
}

Related

Private method testing in NUnit

Issue is simple but quite hard to bypass - I need to test private method without simply changing code to make it public. Doing it wouldn't be the end of the world, but this class contains one public method and set of private methods dedicated to that one public method, and changing it would be bad practice.
I have managed to found "solution" online, but it does not seem to work. Test fails with exception System.Reflection.TargetException : Object does not match target type..
Here is simplified code:
private Class _class;
private List<Item> _list;
private List<Item> _resultList;
[SetUp]
public void SetUp()
{
_class = new Class();
_list = new List<Item>();
_resultList = new List<Item>();
//do stuff to prepare data
}
[Test]
public void TestMethod_Equal()
{
var method = GetMethod("PrivateMethodName");
var result = method.Invoke(this, new object[] { _list }); //this private method needs `List<item>`
Assert.That(_resultList, Is.EqualTo(result));
}
private MethodInfo GetMethod(string methodName) //the online solution
{
if (string.IsNullOrWhiteSpace(methodName))
Assert.Fail("methodName cannot be null or whitespace");
var method = this._class.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
Assert.Fail(string.Format("{0} method not found", methodName));
return method;
}
You need an instance of the class to be able to invoke the method against that instance. You also need to use the same type of said instance when locating the MethodInfo for the class. I've adapted your code to an example below:
void Main()
{
var myInstanceUnderTest = new MyConcreteClass();
var method = myInstanceUnderTest.GetType().GetPrivateMethod("SomePrivateMethod");
method.Invoke(myInstanceUnderTest, null);
}
public class MyConcreteClass
{
private void SomePrivateMethod()
{
Console.WriteLine("I ran!");
}
}
public static class Helpers
{
public static MethodInfo GetPrivateMethod(this Type myType, string methodName) //the online solution
{
if (string.IsNullOrWhiteSpace(methodName))
throw new Exception("methodName cannot be null or whitespace");
var method = myType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
throw new Exception(string.Format("{0} method not found", methodName));
return method;
}
}

Invoking an Interface method using reflection

I am using reflection to invoke an Interface method and I have this error message "Object reference not set to an instance of an object." I try using ConstructorInfo too and also have error. Please help.
public class ClassA
{
private void MethodA(int num, ClassC result)
{
}
}
public interface InterfaceB
{
ClassC MethodB(int num);
}
internal class ClassB
{
public ClassC MethodB(int num)
{
}
}
Type typClassA = Type.GetType("ClassA");
Type typInterfaceB = Type.GetType("InterfaceB");
MethodInfo methodB = typInterfaceB.GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance); // Error lies here
ClassC result = (ClassC) methodB.Invoke(typInterfaceB, new object[]{num});
MethodInfo methodA = typClassA.GetMethod("MethodA", BindingFlags.NonPublic | BindingFlags.Instance);
methodA.Invoke(typClassA, new object[]{num, result});
The actual code for ClassB is not declared as "public ClassB : InterfaceB" but include more classes and ClassB is internal access. See edited codes. Apology for changing the codes so many times as I don't know how to simplify this scenario.
You have to give fully qualified name for class . please observe the below example
namespace ConsoleApplication10
{
interface IA
{
void Print();
}
class A : IA
{
public void Print()
{
Console.WriteLine("Hello");
}
}
class Program
{
static void Main(string[] args)
{
Type type = Type.GetType("ConsoleApplication10.A");
type.GetMethod("Print").Invoke(Activator.CreateInstance(type, null), null);
}
}
}
C# does not use duck-typing.
Therefore in order to actually implement an interface method, you will have to declare that your class implements that interface:
public class ClassB : InterfaceB
There are other problems in your code:
Type typInterfaceB = Type.GetType("InterfaceB"); // unless you have no namespace at all, you need to specify the fully qualified name
// Probably you got an NRE because of above issue here
MethodInfo methodB = typInterfaceB.GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance);
// this does not work, because the first argument needs to be an instance
// try "new ClassB()" instead
ClassC result = (ClassC) methodB.Invoke(typInterfaceB, new object[]{num});
i don't quite understand what you want, but i think you need something like this
public interface InterfaceB
{
int method(int d);
}
public class ClassB:InterfaceB
{
int a = 10;
public int method(int d)
{
return a + d;
}
}
var b = new ClassB();
var mi = typeof(ClassB).GetInterface("InterfaceB").GetMethod("method");
var res = mi.Invoke(b, new object[] { 10 }); // res == 20
UPDATE
yet another variant
public interface InterfaceB
{
int method(int d);
}
public class ClassB:InterfaceB
{
int a = 10;
public int method(int d)
{
return a + d;
}
}
var b = new ClassB();
var mi = typeof(InterfaceB).GetMethod("method");
var res = mi.Invoke(b, new object[] { 10 }); // res == 20
You are trying to invoke a method on an object of type System.Type, and not on the object that implements that interface.
The first parameter of MethodInfo.Invoke is the instance of the object you want to invoke the method on... you are using an instance of a System.Type object, and not one of ClassA or ClassB
All your methods are instance (not static) methods, so you have to create instances to call them, and pass these instances to Invoke, for instance:
// Let's call MethodA from ClassA
Object instanceA = new ClassA();
MethodInfo methodA = instanceA.GetType().GetMethod("MethodA", BindingFlags.NonPublic | BindingFlags.Instance);
// Pay attention to 1st argument - instanceA
methodA.Invoke(instanceA, new object[]{num, result});
...
// Since ClassB doesn't implement InterfaceB, the only option
// is to call MethodB of ClassB
Object instanceB = new ClassB();
MethodInfo methodB = instanceB.GetType().GetMethod("MethodB", BindingFlags.Public | BindingFlags.Instance);
ClassC result = (ClassC) (methodB.Invoke(instanceB, new object[]{num}));
If you are sure your object has needed method then you can use dynamic and write like this:
var result = (yourObject as dynamic).YourMethod("SomeParam");
interface IGetNames
{
string GetFirstName();
string GetMiddleName();
}
public class GetNames : IGetNames
{
public string GetFirstName()
{
return "First Name";
}
public string GetMiddleName()
{
return "Middle Name";
}
}
static void Main(string[] args)
{
Type _Interface = Type.GetType("ConsoleApplication2.IGetNames");
Type _Class = Type.GetType("ConsoleApplication2.GetNames");
InterfaceMapping GetInterfaceMap = _Class.GetInterfaceMap(_Interface);
MethodInfo methodInfo = GetInterfaceMap.TargetMethods[0];
object str = methodInfo.Invoke(Activator.CreateInstance(GetInterfaceMap.TargetType), null);
}

Why does this cloning not work?

I'm trying to clone instances of a derived class, but somehow it doesn't work well. The cloning method is:
public static T CloneFieldsAndProperties<T>(T input)
{
T result = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] listOfProps = typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance);
FieldInfo[] listOfFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance);
foreach (PropertyInfo prop in listOfProps) prop.SetValue(result, prop.GetValue(input, null), null);
foreach (FieldInfo field in listOfFields) field.SetValue(result, field.GetValue(input));
return result;
}
As you can see, I added many BindingFlags because it wasn't working. But to no avail.
It does work in a simple case:
MyclassA1 a1 = new MyclassA1();
MyclassA a = CloneFieldsAndProperties(a1);
if (a is MyclassA1) Text = "Works";
Where:
class MyclassA
{
public int i;
}
class MyclassA1 : MyclassA
{
public int i1;
}
But in my real program it doesn't. The real program's classes' declarations are long so I'm not posting them here. What might be the problem?
I had the same issue a long time ago. The only real solution for me, after lots of googling, was to serialize and deserialize it. It's not a bad solution and you lose only a little bit of performance, just do it like this:
Add this tag to your class:
[Serializable()]
public class a
{
}
And then you can create a function like this:
public object Clone()
{
IO.MemoryStream mem = new IO.MemoryStream();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter form = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
form.Serialize(mem, this);
mem.Position = 0;
return form.Deserialize(mem);
}
If you need a shallow clone, simply use Object.MemberwiseClone. If you need a deep clone, serialize and then deserialize your object (e.g. using BinaryFormatter or DataContractSerializer). This would take care of issues such as cycles and cross references.
This will work and may be faster than the serialization method:
Code:
using System;
namespace Cloning
{
class Program
{
static void Main(string[] args)
{
Derived d = new Derived() { property = 1, field = 2, derivedProperty = 3, derivedField = 4 };
Base b = new Derived(d);
// Change things in the derived class.
d.property = 5;
d.field = 6;
d.derivedProperty = 7;
d.derivedField = 8;
// Output the copy so you know it's not shallow.
Console.WriteLine((b as Derived).property);
Console.WriteLine((b as Derived).field);
Console.WriteLine((b as Derived).derivedProperty);
Console.WriteLine((b as Derived).derivedField);
Console.ReadLine();
}
class Base
{
public int property { get; set; }
public int field;
}
class Derived : Base
{
public Derived() { }
public Derived(Derived d)
{
// Perform the deep copy here.
// Using reflection should work, but explicitly stating them definitely
// will, and it's not like it's not all known until runtime.
this.property = d.property;
this.field = d.field;
this.derivedProperty = d.derivedProperty;
this.derivedField = d.derivedField;
}
public int derivedProperty { get; set; }
public int derivedField;
}
}
}
Test:
http://goo.gl/pQnAL
Output:
1
2
3
4
Comments:
I would really imagine that this would work in more than just a trivial case but perhaps not:
public static T CloneFieldsAndProperties<T>(T input)
{
T result = (T)Activator.CreateInstance(input.GetType());
PropertyInfo[] properties = input.GetType().GetProperties();
FieldInfo[] fields = input.GetType().GetFields();
foreach (PropertyInfo property in properties)
property.SetValue(result, property.GetValue(input, null), null);
foreach (FieldInfo field in fields)
field.SetValue(result, field.GetValue(input));
return result;
}

C# use string as a class field name

Sorry if the tile is misleading. What i would like to do is to use a string to get the values from a class. What i have:
class foo
{
public string field1 {get;set;}
public string field2 {get;set;}
}
public void run()
{
//Get all fields in class
List<string> AllRecordFields = new List<string>();
Type t = typeof(foo);
foreach (MemberInfo m in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
AllRecordFields.Add(m.Name);
}
foo f = new foo();
foreach(var field in AllRecordFields)
{
//field is a string with the name of the real field in class
f.field = "foobar";
}
}
This a really simple example, so the problem is on the line f.field = "foobar";
The field is a string with a name of the real class field what i want to assignt the value to.
Use PropertyInfo instead of MemberInfo and then SetValue.
public void run()
{
foo f = new foo();
Type t = typeof(foo);
foreach (PropertyInfo info in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
info.SetValue(f, "foobar", new object[0]);
}
}
First of all, it is better to use Properties instead of fields.
Second your fields are private, can't be accessed from outside foo. You need to declare them as public.
For your example you have to use reflection to access those files. But that is slow and it is not very good style. You better use the class directly (with property setter) or us an interface.
Add method into foo class to change all properties
class foo
{
public string field1 {get;set;}
public string field2 { get; set; }
public void SetValueForAllString( string value)
{
var vProperties = this.GetType().GetProperties();
foreach (var vPropertie in vProperties)
{
if (vPropertie.CanWrite
&& vPropertie.PropertyType.IsPublic
&& vPropertie.PropertyType == typeof(String))
{
vPropertie.SetValue(this, value, null);
}
}
}
}
foo f = new foo() { field1 = "field1", field2 = "field2" };
f.SetValueForAllString("foobar");
var field1Value = f.field1; //"foobar"
var field2Value = f.field2; //"foobar"

Create an instance of DirectoryEntry for use in test

I'm attempting to create an instance of a DirectoryEntry so that I can use this to test some code that will be passed a DirectoryEntry. However, despite a lot of trying I can't find a way to instantiate a DE and initialize it's PropertyCollection.
I have the following code which was taken and modified from another answer on SO that was doing the same process but for the SearchResult object. It seems that the Add method has been completely disabled and I can't find a way to call a constructor on PropertyCollection to pass in some properties.
using System.Collections;
using System.DirectoryServices;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
public static class DirectoryEntryFactory
{
const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance;
public static DirectoryEntry Construct<T>(T anonInstance)
{
var e = GetUninitializedObject<DirectoryEntry>();
SetPropertiesField(e);
var dictionary = (IDictionary)e.Properties;
var type = typeof(T);
var propertyInfos = type.GetProperties(publicInstance);
foreach (var propertyInfo in propertyInfos)
{
var value = propertyInfo.GetValue(anonInstance, null);
var valueCollection = GetUninitializedObject<PropertyValueCollection>();
var innerList = GetInnerList(valueCollection);
innerList.Add(value);
var lowerKey = propertyInfo.Name.ToLower(CultureInfo.InvariantCulture);
// These both throw exceptions saying you can't add to a PropertyCollection
//(typeof(PropertyCollection)).InvokeMember("System.Collections.IDictionary.Add", nonPublicInstance | BindingFlags.InvokeMethod, null, dictionary, new object[] { propertyInfo.Name, value });
//dictionary.Add(lowerKey, propertyCollection);
}
return e;
}
private static ArrayList GetInnerList(object propertyCollection)
{
var propertyInfo = typeof(PropertyValueCollection).GetProperty("InnerList", nonPublicInstance);
return (ArrayList)propertyInfo.GetValue(propertyCollection, null);
}
private static void SetPropertiesField(DirectoryEntry e)
{
var propertiesField = typeof(DirectoryEntry).GetField("propertyCollection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
propertiesField.SetValue(e, GetUninitializedObject<PropertyCollection>());
}
private static T GetUninitializedObject<T>()
{
return (T)FormatterServices.GetUninitializedObject(typeof(T));
}
}
usage is intended to be
DirectoryEntry e = DirectoryEntryFactory.Construct(new { attr1 = "Hello", attr2 = "World"});
I'm hoping I've missed something as I'm pretty new to using reflection in anger.
I'm not familiar with DirectoryEntry itself, but I'm a big fan of the Adapter pattern for testing. It is an annoyance that you would have to do such a thing, but the code itself is trivial and the classes can be placed in a project folder to hide them away from your main project.
For example, I have a FileInfoAdapter and DirectoryInfoAdapter that wrap those classes that touch the filesystem.
FileInfoAdapter:
public class FileInfoAdapter : IFileInfo
{
private readonly FileSystemInfo _fi;
public FileInfoAdapter(string fileName)
: this(new FileInfo(fileName))
{ }
public FileInfoAdapter(FileSystemInfo fi)
{
_fi = fi;
}
public string Name { get { return _fi.Name; } }
public string FullName { get { return _fi.FullName; } }
public bool Exists { get { return _fi.Exists; } }
}

Categories

Resources