.Net Reflection: how to call a constructor that takes an interface as a parameter

I want to call the constructor via a .Net reflection that takes an interface as a parameter. The code for this class looks something like this:

public interface IStringGetter { string GetString( ); } public class Class1 { private IStringGetter _stringGetter; public Class1( IStringGetter stringGetter ) { _stringGetter = stringGetter; } public String GetString( ) { return _stringGetter.GetString( ); } } 

The code for using this class with reflection is as follows:

  Assembly asm = Assembly.LoadFrom( @"c:\temp\ClassLibrary1.dll" ); Type tClass1 = asm.GetType( "ClassLibrary1.Class1" ); Type tStringGetter = asm.GetType( "ClassLibrary1.IStringGetter" ); ConstructorInfo ci = tClass1.GetConstructor( new Type[ ] { tStringGetter } ); // object obj = ci.Invoke( new object[ ] { *what goes here?* } ); 

And now we need an object that implements the IStringGetter interface. I can not get the object with reflection, because nothing in the library implements the interface. Is there a way to create an object that implements the interface and pass it to the constructor?

I am currently using Windows Forms with Visual Studio 2008, this is a C # project that targets .Net2.0 infrastructure. But I am glad to make any decision.

Edit : Sorry, I did not indicate the problem in full context. Two pieces of code are in different assemblies. The assembly containing the second code snippet does not have a link to the first dll, it just loads the assembly with reflection. If I just write

 public class MyStringGetter : IStringGetter 

the compiler throws an error because IStringGetter is not known at compile time.

Edit2 . Although this is not what I was hoping for, I think the answer is: Do not do this

+4
source share
5 answers

Creating a new class on the fly is never a direct task. You can, as @decyclone says, be able to use a mocking library to create one.

If you need more control over what the interface does than makes a mockery, you may have to go the way of generating code. The System.Reflection.Emit namespace has classes for creating code at runtime. But they are not for the faint of heart.

0
source

If there is no class in Assembly that implements this interface, create a mock that implements this interface in a separate Assembly and uses it.

+4
source

Or call it using null :

 object obj = ci.Invoke( new object[ ] { null } ); 

Or create an instance of a type that implements this interface:

 IStringGetter sg = new StringGetterImpl(); object obj = ci.Invoke( new object[ ] { sg } ); 

If your solution does not have a type that implements this interface, you will have to determine the implementation in the code or dynamically generate a type that implements this interface (for example, you can generate dynamic proxies using the Spring.NET framework).

+1
source

Once upon a time, but try to do something like this.

 class DoClassInvoke { public void InvokeConstructorHaveInterfaceAsParameter() { var class1Type = typeof(Class1); var mainParamConstructor = SummonParameter(class1Type); var mainConstructor = class1Type.GetConstructors().FirstOrDefault(); var mainConstructorDeclare = mainConstructor.Invoke(mainParamConstructor); var mainMethod = class1Type.GetMethod("GetString"); var mainValue = mainMethod.Invoke(mainConstructorDeclare, new object[] { }); } private object[] SummonParameter(Type classTypeData) { var constructorsOfType = classTypeData.GetConstructors(); var firstConstructor = constructorsOfType.FirstOrDefault(); var parametersInConstructor = firstConstructor.GetParameters(); var result = new List<object>(); foreach (var param in parametersInConstructor) { var paramType = param.ParameterType; if (paramType.IsInterface) { var implClassList = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(w => paramType.IsAssignableFrom(w) & !w.IsInterface).ToList(); var implClass = implClassList.FirstOrDefault(); var parameteDatar = SummonParameter(implClass); var instanceOfImplement = (parameteDatar == null || parameteDatar.Length == 0) ? Activator.CreateInstance(implClass) : Activator.CreateInstance(implClass, parameteDatar); result.Add(instanceOfImplement); } } return result.ToArray(); } } 
0
source

I think,

you can use Activator.CreateInstance, see decalization method below

 // Summary: // Creates an instance of the specified type using the constructor that best // matches the specified parameters. // // Parameters: // type: // The type of object to create. // // args: // An array of arguments that match in number, order, and type the parameters // of the constructor to invoke. If args is an empty array or null, the constructor // that takes no parameters (the default constructor) is invoked. // // Returns: // A reference to the newly created object. // // Exceptions: // System.ArgumentNullException: // type is null. // // System.ArgumentException: // type is not a RuntimeType. -or-type is an open generic type (that is, the // System.Type.ContainsGenericParameters property returns true). // // System.NotSupportedException: // type cannot be a System.Reflection.Emit.TypeBuilder.-or- Creation of System.TypedReference, // System.ArgIterator, System.Void, and System.RuntimeArgumentHandle types, // or arrays of those types, is not supported. -or-The constructor that best // matches args has varargs arguments. // // System.Reflection.TargetInvocationException: // The constructor being called throws an exception. // // System.MethodAccessException: // The caller does not have permission to call this constructor. // // System.MemberAccessException: // Cannot create an instance of an abstract class, or this member was invoked // with a late-binding mechanism. // // System.Runtime.InteropServices.InvalidComObjectException: // The COM type was not obtained through Overload:System.Type.GetTypeFromProgID // or Overload:System.Type.GetTypeFromCLSID. // // System.MissingMethodException: // No matching public constructor was found. // // System.Runtime.InteropServices.COMException: // type is a COM object but the class identifier used to obtain the type is // invalid, or the identified class is not registered. // // System.TypeLoadException: // type is not a valid type. public static object CreateInstance(Type type, params object[] args); 
-1
source

All Articles