我从泛型类型开始,我一直坚持我的项目。也许我不太了解仿制药。说明已插入内联。基本上我需要实现Do()方法,但我不知道如何解决< T2>:
public abstract class MyGenericClass<T> { }
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression;
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
// I need to mantain a list of my generic class for later use.
// I don't know T2 at this point.
// So I Chose to use Inheritance as a workaround (MyGenericClass<T> and MyGenericClass<T, T2>).
// Maybe it's not a good solution but I counldn't find out other solution.
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
// I receive the parametric argument T2 here as part of an Expresion.
// And I keep the expression in my list.
public MyGenericClass<T, T2> ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client<T>
{
MyClass<T> class1;
// class1 has been created and his field MyGenericList has beed populated.
// Then when I call Do()....
public void Do()
{
foreach (var item in class1.MyGenericList)
{
// ...I need something like this here,
// but it does not compile because I don't know T2 here.
// The caller of Do() method doesn't know T2.
MyGenericClass<T, T2> myGenericItem = (MyGenericClass<T, T2>)item;
var a = myGenericItem.expression;
}
}
}
答案 0 :(得分:1)
您必须以某种方式提供Do()
T2
参数。所以我的解决方案是创建一个相同类型的方法参数。我还嵌套了类型,以确保它们都引用相同的T
。
我还将参数重命名为更具描述性的
// T -> TArg
// T2 -> TResult
public abstract class MyBaseClass<TArg>
{
public class MyExpressionClass<TResult> : MyBaseClass<TArg>
{
public Expression<Func<TArg, TResult>> Expression { get; private set; }
public MyExpressionClass(Expression<Func<TArg, TResult>> expression)
{
this.Expression=expression;
}
}
public class MyCollectionClass
{
public List<MyBaseClass<TArg>> MyGenericList = new List<MyBaseClass<TArg>>();
public MyExpressionClass<TResult> ReceivingMethod<TResult>(Expression<Func<TArg, TResult>> expression)
{
var genericImp = new MyExpressionClass<TResult>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client
{
public MyCollectionClass List = new MyCollectionClass();
public void Do<TResult>()
{
foreach(var item in List.MyGenericList)
{
var expr = item as MyExpressionClass<TResult>;
if(expr!=null)
{
var a = expr.Expression;
Console.WriteLine(a);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
var client = new MyBaseClass<int>.Client();
// add conversion expressions
client.List.ReceivingMethod((i) => (i).ToString());
client.List.ReceivingMethod((i) => (2*i).ToString());
client.List.ReceivingMethod((i) => (3*i).ToString());
// The programmer has to manually enforce the `string` type
// below based on the results of the expressions above. There
// is no way to enforce consistency because `TResult` can be
// _any_ type.
client.Do<string>();
// Produces the following output
//
// i => i.ToString()
// i => (2*i).ToString()
// i => (3*i).ToString()
}
}
答案 1 :(得分:0)
解决方案1 受到@KMoussa评论的启发。我使用抽象方法将责任委托给MyGenericClass。这似乎是一个更好的设计。所有子类都将实现此方法(DoTheWork())。并且可以从我的Client.Do()方法调用,只有T param:
public abstract class MyGenericClass<T>
{
public abstract string DoTheWork();
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public override string DoTheWork()
{
// .... I can use expression here
}
private Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
// I don't need to cast to MyGenericClass<T, T2>
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
string result = myGenericItem.DoTheWork();
}
}
}
解决方案2 灵感来自@ ja72和@juharr评论。用反射。首先,我使用abstract属性在MyGenericClass上保存类型T2。然后我可以使用反射调用泛型方法(MethodWithArgument),这样我就可以为该转换引入参数:
public abstract class MyGenericClass<T>
{
public abstract Type type { get; set; }
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
type = typeof(T2); // I save the type of T2
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
MethodInfo method = GetType().GetMethod("MethodWithArgument");
MethodInfo generic = method.MakeGenericMethod(new Type[] { myGenericItem.type });
string g = (string)generic.Invoke(this, new object[] { myGenericItem });
}
}
// I introduce T2 in this method
public string MethodWithArgument<T2>(MyGenericClass<T> myClass)
{
// Now, the casting is valid
MyGenericClass<T, T2> mySubClass = (MyGenericClass<T, T2>)myClass;
var a = mySubClass.expression;
// ... I can work with expression here
}
}