.Net Reflection:如何调用以接口作为参数的构造函数

时间:2010-12-08 09:14:42

标签: c# .net reflection

我想通过.Net反射来调用构造函数,该构造函数将接口作为参数。这个类的代码如下所示:

public interface IStringGetter
{
    string GetString( );
}

public class Class1
{
    private IStringGetter _stringGetter;
    public Class1( IStringGetter stringGetter )
    { 
        _stringGetter = stringGetter;
    }

    public String GetString( )
    {
        return _stringGetter.GetString( );
    }
}

使用带反射的此类的代码如下所示:

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

现在需要一个实现IStringGetter接口的对象。我无法通过反射获取对象,因为库中没有任何东西实现了接口。有没有办法创建一个实现接口的对象并将其传递给构造函数?

现在我正在使用Windows Forms和Visual Studio 2008,它是一个针对.Net2.0框架的C#项目。但我很乐意接受任何解决方案。

修改:抱歉,我没有在完整的上下文中说明问题。这两个代码片段位于不同的程序集中。包含第二个代码段的程序集没有对第一个dll的引用,它只是使用反射加载程序集。如果我只是写

public class MyStringGetter : IStringGetter

编译器抛出错误,因为在编译时不知道IStringGetter。

Edit2 :虽然这不是我所希望的,但我认为答案是: 不要那样做

7 个答案:

答案 0 :(得分:4)

如果Assembly中没有实现此接口的类,请创建一个mock,在单独的Assembly中实现该接口并使用它。

答案 1 :(得分:1)

使用null

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

或实例化实现该接口的类型:

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

如果解决方案中没有实现该接口的类型,则必须在代码中定义实现或动态生成实现该接口的类型(例如,您可以使用Spring.NET框架动态生成代理)。

答案 2 :(得分:1)

很久以前,但尝试做这样的事情。

Array

答案 3 :(得分:0)

动态创建新类绝不是一项简单的任务。正如@decyclone所说,您可以使用模拟库来创建一个。

如果您需要更多地控制接口所做的事情,而不是模拟库提供的内容,那么您可能需要沿着代码生成的路线前进。 System.Reflection.Emit命名空间中有一些类专门用于在运行时创建代码。但他们不适合胆小的人。

答案 4 :(得分:0)

我知道我参加聚会有点晚了,但我认为所有答案都走错了路。我假设您想使用一组预定义的已经初始化的字段实例化该类,在整个类中都可以访问这些字段。在这种情况下,请执行以下操作:

全局字段

private IInterface1 IInterface1;
private IInterface2 IInterface2;

构造函数

public Constructor(IInterface1 iInterface1, IInterface2 iInterface2)
{
    this.IInterface1 = iInterface1?? throw new ArgumentNullException(nameof(iInterface1));
    this.IInterface2 = iInterface2?? throw new ArgumentNullException(nameof(iInterface2));
}

方法(反射)

Type classType = typeof(ClassName);
object[] constructorParameters = new object[]
{
    IInterface1,
    IInterface2
};
var instance = Activator.CreateInstance(classType, constructorParameters);

答案 5 :(得分:0)

在需要基于接口创建具体类型的某些情况下,另一种可行的方法是让调用者注册知道类型或任何接口的构建器。

然后,当您需要具体类型时,请查看注册的项目,然后使用注册的具体类型或其生成器来创建它。

MyLib.RegisterType(typeof(IImmutablePerson), typeof(ImmutablePerson))

答案 6 :(得分:-1)

我想

你可以使用Activator.CreateInstance,见下面的方法声明

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