是否可以创建一个实例并转换回通用接口类型?
Is it possible to create an instance and cast back to generic interface type?
我的项目中有以下界面和 classes
public interface IProcessor<T> : where T:IGenericData
{
void Process(T data);
}
public class CompanyADataProcessor : IProcessor<CompanyAData>
{
void Process(CompanyAData Data);
}
CompanyAData 实现 IGenericData。
我想实现下面的转换,可以吗?
(IProcessor<IGenericData>)Activator.CreateInstance(typeof(CompanyADataProcessor));
更新
我想我完全清楚为什么这行不通。我想我需要改变我的设计来解决我当前的问题。
基本上,我目前的问题是我们有一个数据文件处理器,每个客户端都有不同的数据模式,一些客户端数据在保存到我们的数据库之前需要额外清理、重新格式化等,这就是我为什么要这样做的原因之一开始分离 Processor class 来处理特定的客户端数据。
目前的逻辑是首先从配置自定义部分启动所有的处理器,因此,如果我们有一个新的客户端有不同的数据,我们可以很容易地创建一个新的处理器,把dll扔到bin文件夹而不用重启应用。
<Processors>
<add name="CompanyA" type="CompanyA.ThreeStepProcessor,CompanyA.Processor" outputPath="../../Output/CompanyA"/>
.....
</Processors>
不,这不可能。如果是,那么您可以将该接口引用传递给其他代码,它们可以将 IGenericData
的任意实现的实例传递给您的 CompanyADataProcessor
class 的 Process()
方法,当它明确期望只提供 CompanyAData
个实例时。
C# 支持变体通用接口,但即使使用该语法也只允许在另一个方向进行转换,即从 IProcessor<IGenericData>
转换为 IProcessor<CompanyAData>
,而不是相反。鉴于您展示的界面,这是类型安全的唯一方向。
不,这不可能。你能做的就是使用sta方式的界面
(IProcessor<CompanyAData>)Activator.CreateInstance(typeof(CompanyADataProcessor));
或使用方法创建一个说明类型的实例
public T CreateInstance<T, TEntity>()
where T : IProcessor<TEntity>, new()
where TEntity : IGenericData, new()
{
return new T();
}
CreateInstance<CompanyADataProcessor, CompanyAData>();
Peter Duniho 的回答是正确的。你有错误的方差。你的界面可以逆变(“in
”),通过说:
public interface IProcessor<in T> ...
这样只会让您的要求进行相反的转换。
语义原因是 IProcessor<IGenericData>
是可以处理 any IGenericData
的处理器,而 IProcessor<CompanyAData>
保证只处理CompanyAData
。
没有希望使 IProcessor<T>
协变 (如 IProcessor<out T>
),因为 T
显然是在“in
”上下文中使用的。
所以(因为任何 CompanyAData
都是 IGenericData
):
An IProcessor<IGenericData>
is an IProcessor<CompanyAData>
但是:
An IProcessor<CompanyAData>
is not an IProcessor<IGenericData>
这就是逆变的全部内容。
您的 CompanyADataProcessor
是 CompanyAData
的一个名副其实的处理器。它以 CompanyAData
作为输入并对其进行处理。如果将其转换为 IProcessor<IGenericData>
,那么现在要求 相同的对象 处理 any 类型的通用数据。所以不,演员表是不可能的。
我的项目中有以下界面和 classes
public interface IProcessor<T> : where T:IGenericData
{
void Process(T data);
}
public class CompanyADataProcessor : IProcessor<CompanyAData>
{
void Process(CompanyAData Data);
}
CompanyAData 实现 IGenericData。
我想实现下面的转换,可以吗?
(IProcessor<IGenericData>)Activator.CreateInstance(typeof(CompanyADataProcessor));
更新
我想我完全清楚为什么这行不通。我想我需要改变我的设计来解决我当前的问题。
基本上,我目前的问题是我们有一个数据文件处理器,每个客户端都有不同的数据模式,一些客户端数据在保存到我们的数据库之前需要额外清理、重新格式化等,这就是我为什么要这样做的原因之一开始分离 Processor class 来处理特定的客户端数据。
目前的逻辑是首先从配置自定义部分启动所有的处理器,因此,如果我们有一个新的客户端有不同的数据,我们可以很容易地创建一个新的处理器,把dll扔到bin文件夹而不用重启应用。
<Processors>
<add name="CompanyA" type="CompanyA.ThreeStepProcessor,CompanyA.Processor" outputPath="../../Output/CompanyA"/>
.....
</Processors>
不,这不可能。如果是,那么您可以将该接口引用传递给其他代码,它们可以将 IGenericData
的任意实现的实例传递给您的 CompanyADataProcessor
class 的 Process()
方法,当它明确期望只提供 CompanyAData
个实例时。
C# 支持变体通用接口,但即使使用该语法也只允许在另一个方向进行转换,即从 IProcessor<IGenericData>
转换为 IProcessor<CompanyAData>
,而不是相反。鉴于您展示的界面,这是类型安全的唯一方向。
不,这不可能。你能做的就是使用sta方式的界面
(IProcessor<CompanyAData>)Activator.CreateInstance(typeof(CompanyADataProcessor));
或使用方法创建一个说明类型的实例
public T CreateInstance<T, TEntity>()
where T : IProcessor<TEntity>, new()
where TEntity : IGenericData, new()
{
return new T();
}
CreateInstance<CompanyADataProcessor, CompanyAData>();
Peter Duniho 的回答是正确的。你有错误的方差。你的界面可以逆变(“in
”),通过说:
public interface IProcessor<in T> ...
这样只会让您的要求进行相反的转换。
语义原因是 IProcessor<IGenericData>
是可以处理 any IGenericData
的处理器,而 IProcessor<CompanyAData>
保证只处理CompanyAData
。
没有希望使 IProcessor<T>
协变 (如 IProcessor<out T>
),因为 T
显然是在“in
”上下文中使用的。
所以(因为任何 CompanyAData
都是 IGenericData
):
An
IProcessor<IGenericData>
is anIProcessor<CompanyAData>
但是:
An
IProcessor<CompanyAData>
is not anIProcessor<IGenericData>
这就是逆变的全部内容。
您的 CompanyADataProcessor
是 CompanyAData
的一个名副其实的处理器。它以 CompanyAData
作为输入并对其进行处理。如果将其转换为 IProcessor<IGenericData>
,那么现在要求 相同的对象 处理 any 类型的通用数据。所以不,演员表是不可能的。