Dynamic adapter creation for static class from interface - c#

Problem: I want to write test for an application that has many static classes with static methods, so switching a often used class to dependency injection is impossible in one step.
So I want to preserve the static class, create a adapter class with an interface that calls the static methods, so I can use this interface step by step for dependency injection. (as explained here: https://stackoverflow.com/a/2416447/1453662)
But I don't want to write so many adapter classes for all the static classes so my question is if its possible to write a factory that will create a adapter class for a given interface type and a given target static class type e.g.:
// this is the problem
public static class CalculatorStatic {
public static int ComplexCalculation(int a, int b) {
return a + b;
}
}
// I will write this
public interface ICalculator {
int ComplexCalculation(int a, int b);
}
// I don't want to write this
public class CalculatorAdapter : ICalculator {
public int ComplexCalculation(int a, int b) {
return CalculatorStatic.ComplexCalculation(a, b);
}
}
// This should create all adapters for me
public class AdapterFactory {
public T CreateAdapter<T>(Type staticClassType) { // T is the InterfaceType
// Do some magic and return a dynamically created adapter
// that implements the interface and calls the static class
}
}

Instead of returning an interface I would suggest to return a delegate as an adapter.
public static TFunc CreateAdapter<TFunc>(Type staticClass, string methodName)
{
var method = staticClass.GetMethod(methodName,
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
var methodParameters = new ParameterExpression[parameterTypes.Length];
for (int i = 0; i < parameterTypes.Length; i++)
{
methodParameters[i] = Expression.Parameter(parameterTypes[i], "p" + i);
}
var lambda = Expression.Lambda<TFunc>(
Expression.Call(null, method, methodParameters), methodParameters);
return lambda.Compile();
}
And use it like this:
var adapter = CreateAdapter<Func<int, int, int>>(typeof(CalculatorStatic),
nameof(CalculatorStatic.ComplexCalculation));
Console.WriteLine(adapter(1, 2));
If you really-really want to use interfaces (because it has more than one method), you should create an adapter factory for each interface:
public ICalculator CreateAdapter(Type staticClassType)
{
return new CalculatorAdapter(staticClassType);
}
// todo: factory methods for other interfaces, too
And the calculator adapter:
private class CalculatorAdapter: ICalculator
{
private readonly Func<int, int, int> complexCalculationAdapter;
internal CalculatorAdapter(Type staticClassType)
{
complexCalculationAdapter = CreateAdapter<Func<int, int, int>>(staticClassType,
nameof(ICalculator.ComplexCalculation));
// TODO: initialize the other fields if there are more interface methods
}
public int ComplexCalculation(int a, int b)
{
return complexCalculationAdapter(a, b);
}
}
Update
If you really want to create a single method for all interfaces, you should generate a dynamic class.
Please note that this example is not perfect. You should cache the dynamic assembly and module instead of always creating a new one, and if you call ref/out arguments, you should assign them back, etc. But maybe the intention is clear. Tip for the code: compile a code which implements an interface directly and disassemble it to see what code to emit in the generator.
public static T CreateAdapter<T>(Type staticClassType)
{
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(typeof(T).Name + "Adapter"),
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = ab.DefineDynamicModule(typeof(T).Name + "Adapter.dll");
// public class TAdapter : T
TypeBuilder tb = mb.DefineType(typeof(T).Name + "Adapter", TypeAttributes.Public | TypeAttributes.Class,
typeof(object), new Type[] { typeof(T) });
// creating methods
foreach (var methodInfo in typeof(T).GetMethods())
{
var parameters = methodInfo.GetParameters();
var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
var method = tb.DefineMethod(methodInfo.Name,
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
methodInfo.ReturnType, parameterTypes);
// adding parameters
for (int i = 0; i <parameters.Length; i++)
{
method.DefineParameter(i + 1, parameters[i].Attributes, parameters[i].Name);
}
// calling the static method from the body and returning its result
var staticMethod = staticClassType.GetMethod(methodInfo.Name, parameterTypes);
var code = method.GetILGenerator();
for (int i = 0; i < parameters.Length; i++)
{
code.Emit(OpCodes.Ldarg_S, i + 1);
}
code.Emit(OpCodes.Call, staticMethod);
code.Emit(OpCodes.Ret);
}
return (T)Activator.CreateInstance(tb.CreateType());
}
}

Related

Create a delegate from Methodinfo with generic parameter

Based on this old but very usefull article by the legendary Jon Skeet, I wrote a few methods to genereate Action Delegates from MethodInfos for faster invokations. But I ran into an issue, where I am unable to make any progress. See the example below:
public class DataContainer
{
public List<int> myList;
public DataContainer()
{
myList = new List<int>() { 1, 2, 3, 4 };
}
}
public static class ExtensionMethods
{
public static void DoStuff<T>(this IList<T> items)
{
}
}
public class Example
{
private Action<object> doStuffQuickly;
public void Test()
{
var fieldInfo = typeof(DataContainer).GetField("myList");
var doStuffMethod = typeof(ExtensionMethods).GetMethod("DoStuff", BindingFlags.Public | BindingFlags.Static);
var listType = typeof(IList<>).MakeGenericType(fieldInfo.FieldType.GenericTypeArguments);
doStuffQuickly = QuickAccess.CreateWeakActionWithOneParam(doStuffMethod, listType);
var data = new DataContainer();
var list = fieldInfo.GetValue(data);
doStuffQuickly(list);
}
}
public static class QuickAccess
{
private static MethodInfo _weak1ParamActionCreator;
private static MethodInfo Weak1ParamActionCreator => _weak1ParamActionCreator
??= typeof(QuickAccess).GetMethod(nameof(CreateWeakExplicit1ParamAction), BindingFlags.Static | BindingFlags.NonPublic);
public static Action<object> CreateWeakActionWithOneParam(MethodInfo methodInfo, Type paramType0 = null)
{
var parameters = methodInfo.GetParameters();
paramType0 ??= parameters[0].ParameterType;
var creationMethod = Weak1ParamActionCreator.MakeGenericMethod(paramType0);
return (Action<object>)creationMethod.Invoke(null, new object[] { methodInfo });
}
private static Action<object> CreateWeakExplicit1ParamAction<TValue>(MethodInfo methodInfo)
{
var action = CreateStrongExplicit1ParamAction<TValue>(methodInfo);
return (object value) => action((TValue)value);
}
private static Action<TValue> CreateStrongExplicit1ParamAction<TValue>(MethodInfo methodInfo)
{
//Debug.Log(methodInfo.GetParameters()[0].ParameterType.Name + " <-> " + typeof(TValue).Name);
//Debug.Log(PrintTypes(methodInfo.GetParameters()[0].ParameterType.GenericTypeArguments) + " <-> "
// + PrintTypes(typeof(TValue).GenericTypeArguments));
return (Action<TValue>)Delegate.CreateDelegate(typeof(Action<TValue>), methodInfo);
}
private static string PrintTypes(Type[] types)
{
return string.Join(", ", types.Select(t => t.Name));
}
}
This fails with ArgumentException: method arguments are incompatible when trying to create the delegate.
The commented logs print IList`1 <-> IList`1 and T <-> Int32, which made me think that maybe
var listType = typeof(IList<>).MakeGenericType(fieldInfo.FieldType.GenericTypeArguments);
should instead simply be
var listType = typeof(IList<>);
but that is causing an InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
I don't know how to proceed from here. Any help will be appreciated.
If I understand the code correctly, listType would be a IList<int>, so DoStuff would be DoStuff<IList<int>>. I would expect it to be DoStuff<int>
So the correct version should be
var listItemType = fieldInfo.FieldType.GenericTypeArguments[0];
doStuffMethod = doStuffMethod.MakeGenericMethod(listItemType);
doStuffQuickly = QuickAccess.CreateWeakActionWithOneParam(doStuffMethod);
I would highly recommend running your code in a debugger and inspect your values in every step to confirm all your reflection types look like you expect. Reflection is difficult, so it is really useful to be able to confirm any assumptions.

C# Create lambda over given method that injects first paramater

In C# I have following methods defined in given class (non static):
int MyMethod(ScriptEngine script, int a, int b) {
return a + b;
}
void MyMethod2(ScriptEngine script, string c) {
// do something with c
}
I want to create wrapping lambda / Action / Delegate / MethodInfo (all are accepted by script engine) that automatically passes ScriptEngine and this from given, predefined variables.
So far I've experimenting with:
// With overloads up to 16 template parameters
Action<T1> Wrap<T1>(Action<ScriptEngine, T1> func, ScriptEngine script) {
return (Action<T1>) ((t1) => func(script, t1));
}
But when called on MyMethod2 I've got The type arguments for method … cannot be inferred from the usage. Try specifying the type arguments explicitly. If I specify the template arguments explicity, it works, but I want to avoid such specification.
Is there any other way (not neccesery following my solution) I can create such wrapper automatically (or semi-automatically)?
It is worth mentioning that there is a dedicated abstract method void RegisterAll(ScriptEngine script) that can register required members of given subclass.
Here is an example of what I am trying to achieve:
class ScriptEngine { // Stub to have complete example, actual implementation is defined elsewhere
void RegisterApi(string name, MethodInfo methodInfo) { }
void RegisterApi(string name, Delegate delegateSelf) { }
}
class Api {
int MyMethod(ScriptEngine script, int a, int b) {
return a + b;
}
void MyMethod2(ScriptEngine script, string c) {
// do something with c
}
void RegisterAll(ScriptEngine script) {
// Is there any way to shorten this up (not providing MyMethod twice, not providing template arguments?)
script.RegisterApi(nameof(MyMethod), (Delegate)Wrap<string>(MyMethod, script));
}
}
The problem is how to improve this RegisterApi method so it:
Takes the method only once
Does not require specifying arguments via template method
There is actually another solution that does not involve emiting new Expressions (could fail on iOS!)
First, let us define following wrapper:
private class Wrapper
{
public readonly object container;
public readonly MethodInfo method;
public readonly ScriptEngine engine;
public Wrapper(object container, MethodInfo method, ScriptEngine engine)
{
this.container = container;
this.method = method;
this.engine = engine;
}
public Action CreateAction()
{
return () => method.Invoke(container, new object[] { engine });
}
public Action<T1> CreateAction<T1>()
{
return (arg1) => method.Invoke(container, new object[] { engine, arg1 });
}
// etc
}
Now you can register method like that:
var type = typeof(Wrapper);
var instance = Activator.CreateInstance(type, new object[] { container, methodInfo, engine });
MethodInfo methodActual = null;
if (methodInfo.ReturnType == typeof(void))
{
var methods = type.GetMethods().Where(x => x.Name == "CreateAction");
foreach (var method in methods)
{
if (method.GetGenericArguments().Length == methodInfo.GetParameters().Length - 1)
{
methodActual = method.MakeGenericMethod(methodInfo.GetParameters().Skip(1).Select(x => x.ParameterType).ToArray());
}
}
}
var actionToRegister = methodActual.Invoke(instance, new object[0]);
The solution is to use Expression Tree to create a simple delegate wrapper.
var parameterEngine = Expression.Constant(script, typeof(ScriptEngine));
var parameterCaller = Expression.Constant(this, this.GetType());
// Build parameters, skipping the first. Note that trailing "ToList" is important!
var parameters = methodInfo.GetParameters().Skip(1).Select(x => Expression.Parameter(x.ParameterType, x.Name)).ToList();
// Inject parameter
var mergedParameters = new List<Expression>();
mergedParameters.Add(parameterEngine);
mergedParameters.AddRange(parameters);
// Bind together
var call = Expression.Call(parameterCaller, methodInfo, mergedParameters);
var expression = Expression.Lambda(call, parameters);
var method = expression.Compile();
// Method can now be registered

How can I create a derived type from T, using System.Reflection.Emit

what I am having difficulties understanding is : what should I do in the build method?
It is our intent to implement a framework that has a method that generates a new instance of a class of domain in which their properties and methods have added functionalities.
The Following example presents a case of the creation of a object of domain Stock where the parameters passed to build will be pass as arguments to the constructor of stock in it's instantiation.
Enhancer.Build<Stock>("Apple", "Dow Jones");
The added functionalities are specified by custom attributes that mark the virtual methods and properties, as the following example shows. In the comments it is said what we intend the marked methods and properties to start verifying in the returned object from the function Build of Enhancer.
Every custom attribute in the example should have a common base type - EnhancedAtributte - with an abstract method Check(object[] args) that receives the arguments from the marked method.
class Stock
{
public Stock(string name, string index) { ... }
[NonNull]
public virtual string Market { get; set; } // set will launch an exception if values are null
[Min(73)]
public virtual long Quote { get; set; } // set will launch an exception if values are < 73
[Min(0.325)]
public virtual double Rate { get; set; } // set will launch an exception if values are < 0.325
[Accept("Jenny", "Lily", "Valery")]
public virtual string Trader{get; set; } // set will launch an exception if values are different than Jenny, Lily or Valery
[Max(58)]
public virtual int Price { get; set; } // set will launch an exception if values are > 58
// it will launch exception if the state of this or any of the parameters has been altered by the execution of a marked method
// -- BuildInterest
[NoEffects]
public double BuildInterest(Portfolio port, Store st) { ... }
}
Implementation strategies:
The project Enhancer must use the System.Reflection.Emit API.
The solution must not be compromised with the given examples.
A function Build(params object[] args) should return a new instance of a new class derived from T, let's call it T’, that
redefines the virtual methods of T.
The new class T’ is created dynamically with the API resource System.Reflection.Emit.
For each M method in T that is marked ( Custom Attribute), it should be created a new definition of the method M’ in class T’.
The
method M’ should call the base method M and should do the specified
by the custom attribute.
I'd start by verifying that T is neither sealed nor abstract. That should be sufficient to make sure it's (1) a class; and (2) capable of being extended.
Next, iterate over typeof(T).GetProperties() to find any 'enhanced' properties where CanWrite is true and property.GetCustomAttributes<EnhancedAtributte>().Any() reports true. If there aren't any matching properties, you can just instantiate T directly.
Since the property values are validated by the attribute instances themselves, you'll want to cache the attributes somewhere, lest you incur an expensive lookup on each property change. You should aim to generate a class that looks something like this:
public class __Enhanced__Stock__ {
private static readonly EnhancedAttribute[] __Price__Attributes__;
static __Enhanced__Stock__() {
__Price__Attributes__ = typeof(Stock).GetProperty("Price")
.GetCustomAttributes<EnhancedAtributte>()
.ToArray();
}
public override int Price {
get => base.Price;
set {
for (int i = 0, n = __Price__Attributes__.Length; i < n; i++)
__Price__Attributes__[i].Check(new Object[] { (Object)value });
}
base.Price = value;
}
}
}
A TypeBuilder can be created from a ModuleBuilder, which is created from an AssemblyBuilder. For the latter two, you can just keep a static instance around.
You'll need to use TypeBuilder.DefineField to define a static field to use as an attribute cache for each property (or use a single EnhancedAttribute[][] indexed by property). In either case, you'll have to define a class constructor (see TypeBuilder.DefineTypeInitializer) to initialize the cache. You'll have to write the IL yourself using MethodBuilder.GetILGenerator().
For each enhanced property you found, you'll need to define a new property with the same name (see TypeBuilder.DefineProperty), and emit a separate get and set accessor for each (see TypeBuilder.DefineMethod). Each accessor will need to be bound to the property, which can be accomplished via PropertyBuilder.SetGetMethod and SetSetMethod. You'll also have to make the accessors override the accessors in T, which you can do via TypeBuilder.DefineMethodOverride. You can see some hints on overriding properties in this question.
The code for the get accessor override will be simple: you need only delegate to the base property. The set accessor is more complicated, because you'll need to loop over the attribute cache for the property and call each attribute's Check method. Again, you'll need to emit the IL manually, which includes figuring out how to emit a simple for loop. Alternatively, since you already know the number of attributes for each property, you could just write a manually-unrolled loop. Regardless, for each call to Check, remember that you'll need to initialize a new object[] containing into which you must copy your value parameter.
Once you've declared the attribute cache field(s), the type initializer, the properties, and their accessors, you're essentially finished. You can 'bake' the derived type by calling CreateType() on your TypeBuilder.
Partial Solution
I felt like writing some code, so here's a solution that should handle the attribute-based property validation. It's not entirely clear to me how the attributes on other methods should work, but this should provide a good starting point nonetheless.
public class Enhancer
{
private static readonly ModuleBuilder ModuleBuilder;
static Enhancer()
{
var b = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.Run);
ModuleBuilder = b.DefineDynamicModule($"{b.GetName().Name}.Module");
}
private const BindingFlags InstanceFlags = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic;
private const FieldAttributes CacheFlags = FieldAttributes.Private |
FieldAttributes.Static |
FieldAttributes.InitOnly;
private const TypeAttributes TypeFlags = TypeAttributes.Public |
TypeAttributes.Sealed |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout |
TypeAttributes.AnsiClass;
private static IEnumerable<PropertyInfo> FindEnhancedProperties(Type t)
{
foreach (var p in t.GetProperties(InstanceFlags))
{
if (p.CanWrite &&
p.GetSetMethod(true).IsVirtual &&
p.IsDefined(typeof(EnhancedAttribute)))
{
yield return p;
}
}
}
public static EnhancedAttribute[] FindEnhancedAttributes(PropertyInfo p)
{
return p.GetCustomAttributes<EnhancedAttribute>().ToArray();
}
private static readonly MethodInfo CheckMethod =
typeof(EnhancedAttribute).GetMethod(
nameof(EnhancedAttribute.Check),
new[] { typeof(object[]) });
private static readonly MethodInfo GetTypeFromHandleMethod =
typeof(Type).GetMethod(
nameof(Type.GetTypeFromHandle),
new[] { typeof(RuntimeTypeHandle) });
private static readonly MethodInfo GetPropertyMethod =
typeof(Type).GetMethod(
nameof(Type.GetProperty),
new[] { typeof(string), typeof(BindingFlags) });
private static readonly MethodInfo FindEnhancedAttributesMethod =
typeof(Enhancer).GetMethod(
nameof(FindEnhancedAttributes),
new[] { typeof(PropertyInfo) });
private readonly Type _base;
private readonly TypeBuilder _enhanced;
private readonly PropertyInfo[] _properties;
private readonly FieldBuilder[] _attributeCaches;
private readonly MethodBuilder[] _propertySetters;
private static readonly Dictionary<Type, Type> Cache = new Dictionary<Type, Type>();
public static T Build<T>(params object[] args) where T : class
{
Type type;
lock (Cache)
{
if (!Cache.TryGetValue(typeof(T), out type))
Cache[typeof(T)] = type = new Enhancer(typeof(T)).Enhance();
}
return (T)Activator.CreateInstance(type, args);
}
private Enhancer(Type t)
{
if (t?.IsSealed != false || t.IsInterface)
{
throw new ArgumentException(
"Type must be a non-sealed, non-abstract class type.");
}
_base = t;
_enhanced = ModuleBuilder.DefineType($"<Enhanced>{t.FullName}", TypeFlags, t);
_properties = FindEnhancedProperties(t).ToArray();
_attributeCaches = _properties.Select(
p => _enhanced.DefineField(
$"__{p.Name}Attributes",
typeof(EnhancedAttribute[]),
CacheFlags)).ToArray();
_propertySetters = new MethodBuilder[_properties.Length];
}
private Type Enhance()
{
GenerateTypeInitializer();
for (int i = 0, n = _properties.Length; i < n; i++)
EnhanceProperty(i);
GenerateConstructors();
return _enhanced.CreateType();
}
private void GenerateConstructors()
{
var baseCtors = _base.GetConstructors(InstanceFlags);
foreach (var baseCtor in baseCtors)
{
if (baseCtor.IsPrivate)
continue;
var parameters = baseCtor.GetParameters();
var ctor = _enhanced.DefineConstructor(
baseCtor.Attributes,
baseCtor.CallingConvention,
parameters.Select(p => p.ParameterType).ToArray());
var il = ctor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < parameters.Length; i++)
il.Emit(OpCodes.Ldarg, i + 1);
il.Emit(OpCodes.Call, baseCtor);
il.Emit(OpCodes.Ret);
}
}
private void GenerateTypeInitializer()
{
var typeInit = _enhanced.DefineTypeInitializer();
var il = typeInit.GetILGenerator();
for (int i = 0, n = _properties.Length; i < n; i++)
{
var p = _properties[i];
il.Emit(OpCodes.Ldtoken, _base);
il.EmitCall(OpCodes.Call, GetTypeFromHandleMethod, null);
il.Emit(OpCodes.Ldstr, p.Name);
il.Emit(OpCodes.Ldc_I4_S, (int)InstanceFlags);
il.EmitCall(OpCodes.Call, GetPropertyMethod, null);
il.EmitCall(OpCodes.Call, FindEnhancedAttributesMethod, null);
il.Emit(OpCodes.Stsfld, _attributeCaches[i]);
}
il.Emit(OpCodes.Ret);
}
private void EnhanceProperty(int index)
{
var p = _properties[index];
var property = _enhanced.DefineProperty(
p.Name,
p.Attributes,
p.PropertyType,
null);
var baseSet = p.GetSetMethod(true);
var set = _enhanced.DefineMethod(
baseSet.Name,
baseSet.Attributes & ~MethodAttributes.NewSlot | MethodAttributes.Final,
baseSet.CallingConvention,
baseSet.ReturnType,
new[] { p.PropertyType });
property.SetSetMethod(set);
_enhanced.DefineMethodOverride(set, baseSet);
var il = set.GetILGenerator();
var attributeCount = p.GetCustomAttributes<EnhancedAttribute>().Count();
for (int j = 0; j < attributeCount; j++)
{
il.Emit(OpCodes.Ldsfld, _attributeCaches[index]);
il.Emit(OpCodes.Ldc_I4, j);
il.Emit(OpCodes.Ldelem_Ref, j);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Newarr, typeof(object));
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ldarg_1);
if (p.PropertyType.IsValueType)
il.Emit(OpCodes.Box, p.PropertyType);
il.Emit(OpCodes.Stelem_Ref);
il.EmitCall(OpCodes.Callvirt, CheckMethod, null);
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Call, baseSet, null);
il.Emit(OpCodes.Ret);
_propertySetters[index] = set;
}
}

How can I create new object based on another one?

I have some not useful object with, let's say, 30 properties. Half of them are useful for me, so I want to create new useful object with only properties I need so the rest doesn't take space in object visualizers. I don't want to define new class and type them down. I want something like
var list = new List<SomeType> { usefulProp1, usefulProp2, ... };
var usefulObject = new NewItem(notUsefulObject, list);
where SomeType is not string (list doesn't contain property names).
if its something permanent then doing it properly would be to create a class that inherits from your base class and populate only the properties that you need.
public UsefulObject : NotUsefulObject
{
public int MyProperty
{
get
{
return base.MyProperty; // this is arbitrary you can do it however you want.
}
set
{
MyProperty = value;
}
}
}
Then you can use your reuse your useful object however you want.
var list = new List<UsefulObject>();
var list = new List<Expression<Func<object>>> { () => notUsefulObject.usefulProp1, () => notUsefulObject.usefulProp2... };
var nm = new AssemblyName("MyDynamicAssembly");
TypeBuilder tb = Thread.GetDomain().DefineDynamicAssembly(nm, AssemblyBuilderAccess.RunAndSave).DefineDynamicModule(nm.Name, nm.Name + ".dll").DefineType("NewItem", TypeAttributes.Public);
const MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
foreach (Expression b in list.Select(x => x.Body))
{
MemberInfo mi = ((MemberExpression)b).Member;
Type t = b.Type;
FieldBuilder fb = tb.DefineField(mi.Name.ToLower(), t, FieldAttributes.Private);
PropertyBuilder pb = tb.DefineProperty(mi.Name, PropertyAttributes.HasDefault, t, null);
MethodBuilder getBld = tb.DefineMethod("get_" + mi.Name, GetSetAttr, t, Type.EmptyTypes);
ILGenerator getGen = getBld.GetILGenerator();
getGen.Emit(OpCodes.Ldarg_0);
getGen.Emit(OpCodes.Ldfld, fb);
getGen.Emit(OpCodes.Ret);
MethodBuilder setBld = tb.DefineMethod("set_" + mi.Name, GetSetAttr, null, new[] { t });
ILGenerator setGen = setBld.GetILGenerator();
setGen.Emit(OpCodes.Ldarg_0);
setGen.Emit(OpCodes.Ldarg_1);
setGen.Emit(OpCodes.Stfld, fb);
setGen.Emit(OpCodes.Ret);
pb.SetGetMethod(getBld);
pb.SetSetMethod(setBld);
}
object usefulObject = Activator.CreateInstance(tb.CreateType());
Because you said this problem was specific to object visualizers, the best solution is to make a Debugger Type Proxy for the class which can be used as a proxy.
[DebuggerTypeProxy(typeof(SomeTypeDebugView))]
public class SomeType
{
public string Foo { get; set; }
public string Bar { get; set; }
internal class SomeTypeDebugView
{
private SomeType _someType;
public SomeTypeDebugView(SomeType someType)
{
_someType = someType;
}
public string Foo { get { return _someType.Foo; } }
}
}
class Program
{
static void Main()
{
var someType = new SomeType();
someType.Foo = "foo";
someType.Bar = "bar";
Debugger.Break();
}
}
This will cause Bar to be hidden in the debug visualizer by default unless you choose to view the "Raw Type"
If you are looking for a more one time debugging type you can use annonamous types to create the new type you need in the watch window, for example his is new {Foo = someType.Foo, Bar = someType.Bar }
This also could be used with LINQ to perform the select over a IEnumerable, here for example is someTypeList.Select(x=> new {Foo = x.Foo, Bar = x.Bar})

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);
}

Categories

Resources