我有一个像
这样的基类abstract class A <TEntity, TLog>
{
public abstract TLog Get(TEntity entity);
}
和少数子类如
class B : A<Branch, BranchLog>
{
public override BranchLog Get(Branch entity)
{
return null;
}
}
现在可以获取子类的实例,具体取决于它的基类的通用实现,如
class Mapper
{
public TLog GetMapped<TEntity, TLog>(TEntity entity)
{
/*if called with GetMapped<Branch, BranchLog>, make instance of B b = new B()*/
/*returng b.Get(entity)*/
return null;
}
}
或任何方式而不是反思
答案 0 :(得分:3)
添加一个告诉类型的通用参数。使用new()
约束新的通用参数,以便我们可以新建它A<TEntity, TLog>
以确保只传递A
或其子类的实例。
class Mapper
{
public TLog GetMapped<TType, TEntity, TLog>(TEntity entity) where TType : A<TEntity, TLog>, new()
{
TType instance = new TType();
return instance.Get(entity);
}
}
然后将其称为
Mapper mapper = new Mapper();
mapper.GetMapped<B, Branch, BranchLog>(branch);
答案 1 :(得分:1)
或任何方式而不是反思
确定。旧式if
声明:
public TLog GetMapped<TEntity, TLog>(TEntity entity)
{
if(typeof(TEntity) == typeof(Branch) && typeof(TLog) == typeof(BranchLog))
{
B b = new B();
return (TLog)b.Get((Branch)entity);
}
return default(TLog);
}
但这并不适合使用泛型或继承。您确定自己并未尝试解决XY problem吗?
答案 2 :(得分:0)
这里的问题是除了B
之外的任何类都可以扩展通用实例A<Branch,BranchLog>
所以这要求编译器说&#34;如果B
是唯一的A<Branch,BranchLog>
的子类给我一个B
&#34;的实例?如果没有其他符号将B
专门链接到Mapper类中的特定泛型方法,编译器就无法自行决定。如果你试图完成这个&#34;自动化&#34;没有泛型或Branch,BranchLog
- >的其他明确链接B
那么你基本上要求编译器自动化相当于:
assembly.GetTypes().Where(t => typeof(B).BaseType == t).FirstOrDefault()
这不是特定于泛型的。我们可以使用简单类A<Branch,BranchLog>
替换A1
实例,而无需泛型即可重写此问题。
class A {}
class A1 : A {}
class B : A1 {}
class Mapper {
void Fun(A1) {
// How to get B b = new B() since I know A1
// There is no automatic way at compile time, using the type system
}
}
因为没有什么能阻止我宣布:
class C : A1 {}
class D : A1 {}
现在B
,C
和D
都是A1
的实例。
我认为你需要重新思考你的班级设计。
如果您无法修改Mapper类,请考虑某种通用工厂类或方法。您应该能够编写具有3个泛型类型参数的工厂方法,这些参数将特定子类(B
)映射到用于A<TEntity,TLog>
的特定通用实例参数。
public V GetMapped<T,U,V>(U u) { return new T().Get(U) as V; }
借助其他机制来决定哪个班级映射到您的&#34;签名&#34;如其他答案中所列(RTTI /是/ as)。但在我看来,如果您已经在使用泛型,那么您应该坚持使用通用解决方案。
答案 3 :(得分:-1)
嗯,你可以在没有反射的情况下做到这一点,但是你需要知道可能分别为TEntity和TLOG推断出的所有可能的类型。
尝试
public TLog GetMapped<TEntity, TLog>(TEntity entity)
{
if(typeof(TEntity) == typeof(Branch) && typeof(TLog) == typeof(BranchLog))
{
B b = new B();
return b.Get(entity);
}
return null;
}
但您也可以在派生类型B中覆盖GetMapped方法,以获取此类的实例,您可以在其中调用b.Get(entity)
但是,如果还有更多这种单一类型(通常情况下是泛型,为什么还要使用它们?!),这不是真正的好选择。
答案 4 :(得分:-1)
有趣的是,通过制作GetMapped&lt;&gt;像这样的泛型,Mapper类的客户端已经必须确切地知道应该存在哪个映射。无论具体实施如何,我都会重新考虑你在这里要做的事情。您是否可以更具体地了解GetMapped&lt;&gt; -method将首先用于什么?
编辑:为了尝试发布替代解决方案,为什么不将子类的特定实例放入Mapper类中的实际Dictionary中:
public class Mapper
{
private readonly Dictionary<Type, object> _instances;
public Mapper()
{
_instances = new Dictionary<Type, object>()
{
{ typeof(Branch), new B() },
...
};
}
public TLog GetMapped<TEntity, TLog>(TEntity entity)
{
A<TEntity, TLog> a = (A<TEntity, TLog>) _instances[typeof(TEntity)];
return a.Get(entity);
}
}