我想通过.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 :虽然这不是我所希望的,但我认为答案是: 不要那样做
答案 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);