使用带有泛型的基 class 创建类型的实例
Create Instance of type using base class with generics
我在我的代码中创建了一个插件系统,它从 DLLS 加载类型。我使用这段代码从加载的 DLL 中获取我想要的类型;
var type = Assembly.LoadFrom(filePath).GetTypes()
.FirstOrDefault(t =>
t.IsClass && t.IsSubclassOfRawGeneric(typeof(DespatchBasePlugin<>)));
IsSubClassOfRawGeneric 寻找基本类型,因为它被埋没了几个 classes,代码工作并返回正确的类型。
然后我使用 Activator 创建此 class 的一个实例;
DespatchBasePlugin<XMLSettingBase> obj = Activator.CreateInstance(type, new object[] { logger }) as DespatchBasePlugin<XMLSettingBase>;
不幸的是,这一行的转换创建了一个空引用。删除强制转换 returns 一个有问题的 class 的实例,但我需要存储它作为它的基本类型。
这是正在加载的 class(为简洁起见缩短);
public class DHLPlugin : DespatchBasePlugin<UserSetting>
{
public DHLPlugin(BaseForm logger) : base("DHL", logger)
{
this.order = 10;
}
}
这是我想要它使用的基础 class(注意 class 本身有一个基础 class,它有几层深);
public abstract class DespatchBasePlugin<TSettings> : DespatchBase<TSettings> where TSettings : XMLSettingBase, new()
之前的代码使用了一个基 class,没有分配给它泛型并且工作得非常好。看起来像这样;
DespatchBasePlugin obj = Activator.CreateInstance(type, new object[] { logger }) as DespatchBasePlugin;
我确定我在做一些愚蠢的事情,请告诉我它是什么。
编辑 - 未将此标记为重复,因为我认为这是一个比另一个更好的 question/answer,后者由 MSDN 的通用 link 作为答案。如果这不是使用复制系统的正确方法,请告诉我。
您可以使用逆变来定义您的插件:
public class Program
{
public static void Main()
{
var settings = new DerivedSettings()
{Name = "John"};
DerivedPlugin a = new DerivedPlugin(settings);
IPlugin<BaseSettings> sample = (IPlugin<BaseSettings>)a;
Console.WriteLine(sample.GetName());
}
}
public abstract class BaseSettings
{
public abstract string Name
{
get;
set;
}
}
public interface IPlugin<out TSettings>
where TSettings : BaseSettings
{
string GetName();
}
public abstract class BasePlugin<TSettings> : IPlugin<TSettings> where TSettings : BaseSettings
{
protected readonly TSettings _settings;
public BasePlugin(TSettings settings)
{
_settings = settings;
}
public virtual string GetName()
{
return _settings.Name;
}
}
public class DerivedSettings : BaseSettings
{
public override string Name
{
get;
set;
}
}
public class DerivedPlugin : BasePlugin<DerivedSettings>
{
public DerivedPlugin(DerivedSettings settings): base (settings)
{
}
}
我已经包含了一个 BasePlugin class,但这是可选的,您可以直接使用该接口。
我在我的代码中创建了一个插件系统,它从 DLLS 加载类型。我使用这段代码从加载的 DLL 中获取我想要的类型;
var type = Assembly.LoadFrom(filePath).GetTypes()
.FirstOrDefault(t =>
t.IsClass && t.IsSubclassOfRawGeneric(typeof(DespatchBasePlugin<>)));
IsSubClassOfRawGeneric 寻找基本类型,因为它被埋没了几个 classes,代码工作并返回正确的类型。
然后我使用 Activator 创建此 class 的一个实例;
DespatchBasePlugin<XMLSettingBase> obj = Activator.CreateInstance(type, new object[] { logger }) as DespatchBasePlugin<XMLSettingBase>;
不幸的是,这一行的转换创建了一个空引用。删除强制转换 returns 一个有问题的 class 的实例,但我需要存储它作为它的基本类型。
这是正在加载的 class(为简洁起见缩短);
public class DHLPlugin : DespatchBasePlugin<UserSetting>
{
public DHLPlugin(BaseForm logger) : base("DHL", logger)
{
this.order = 10;
}
}
这是我想要它使用的基础 class(注意 class 本身有一个基础 class,它有几层深);
public abstract class DespatchBasePlugin<TSettings> : DespatchBase<TSettings> where TSettings : XMLSettingBase, new()
之前的代码使用了一个基 class,没有分配给它泛型并且工作得非常好。看起来像这样;
DespatchBasePlugin obj = Activator.CreateInstance(type, new object[] { logger }) as DespatchBasePlugin;
我确定我在做一些愚蠢的事情,请告诉我它是什么。
编辑 - 未将此标记为重复,因为我认为这是一个比另一个更好的 question/answer,后者由 MSDN 的通用 link 作为答案。如果这不是使用复制系统的正确方法,请告诉我。
您可以使用逆变来定义您的插件:
public class Program
{
public static void Main()
{
var settings = new DerivedSettings()
{Name = "John"};
DerivedPlugin a = new DerivedPlugin(settings);
IPlugin<BaseSettings> sample = (IPlugin<BaseSettings>)a;
Console.WriteLine(sample.GetName());
}
}
public abstract class BaseSettings
{
public abstract string Name
{
get;
set;
}
}
public interface IPlugin<out TSettings>
where TSettings : BaseSettings
{
string GetName();
}
public abstract class BasePlugin<TSettings> : IPlugin<TSettings> where TSettings : BaseSettings
{
protected readonly TSettings _settings;
public BasePlugin(TSettings settings)
{
_settings = settings;
}
public virtual string GetName()
{
return _settings.Name;
}
}
public class DerivedSettings : BaseSettings
{
public override string Name
{
get;
set;
}
}
public class DerivedPlugin : BasePlugin<DerivedSettings>
{
public DerivedPlugin(DerivedSettings settings): base (settings)
{
}
}
我已经包含了一个 BasePlugin class,但这是可选的,您可以直接使用该接口。