我有一个界面
public interface ICallback<T>
{
void OnSuccess (T data);
void OnFailure (Exception exception);
}
和一个班级
public class ToDoTask
{
private int someInt;
public string StringProperty {get; set;}
public ICallback Callback {get; private set;}
}
这不会编译,因为它要我专门化Callback
属性。我不想专门从事物业,因为我不知道这种类型。该类型在运行时通过反射确定。
以下是对所发生情况的一个小解释:
CreateInterfaceProxyWithoutTarget<C>
)以实现给定的接口(让我们调用此IModel
)IModel
中定义)决定需要完成的操作ICallback<T>
,则会将其分配给Callback
属性,否则它是null
。这就是Interceptor类的样子:
public class Intercepteur : IInterceptor{
public void Intercept(IInvocation invocation) {
ToDoTask task = Study(invocation);
/*
nothing past this point is actually written,
so there may be typos or compile errors below
*/
try
{
var result = Perform(task);
if (null != task.Callback)
task.Callback.OnSuccess (MagicalTransformation (result, typeof (T)));
} catch (Exception e)
{
if (null != task.Callback)
task.Callback.OnFailure (e);
}
}
}
将回调声明为ICallback<object>
并强制转换是否安全?在运行时返回?
如果上述任何一个听起来很愚蠢,那是因为我在C#中没有太多的反思经验,而且在没有碰到它的大约4年后我深入c#潜水。太好了!
答案 0 :(得分:3)
您需要定义T
是什么,或使用其他选项。
解决这个问题的三种最简单方法是:
由T
ToDoTask<T>
public interface ICallback<T> {
void OnSuccess (T data);
void OnFailure (Exception exception);
}
public class ToDoTask<T> {
private int someInt;
public string StringProperty {get; set;}
public ICallback<T> Callback {get; private set;}
}
将OnSuccess
方法定义为通用,而不是界面
public interface ICallback
{
void OnSuccess<T>(T data);
void OnFailure(Exception exception);
}
public class ToDoTask<T>
{
private int someInt;
public string StringProperty { get; set; }
public ICallback Callback { get; private set; }
}
使用object
代替T
public interface ICallback {
void OnSuccess (object data);
void OnFailure (Exception exception);
}
public class ToDoTask {
private int someInt;
public string StringProperty {get; set;}
public ICallback Callback {get; private set;}
}
答案 1 :(得分:1)
ICallBack
不存在,必须为ICallBack<T>
,因此您需要提供类型 - 或使ToDoTask
泛型并将类型传递给ICallBack
。
class ToDoTask<T>{
...
ICallBack<T> CallBack {get;set;}
}
然后在反射之后传递类型或其他任何内容。
不太安全的选择是使用dynamic
。这是一个示例程序,试图执行类似于您尝试的操作
class Program
{
interface ICallBack<T>
{
void SetObject(T obj);
}
class CallBackUser<T>
{
public dynamic CB { get; set; }
}
class CB<T> : ICallBack<T>
{
public void SetObject(T obj)
{
Console.WriteLine("Works");
}
}
static Type GetMyTypeThroughReflection()
{
return typeof (int);
}
static void Main(string[] args)
{
Type t = GetMyTypeThroughReflection();
Type genericClass = typeof(CallBackUser<>);
Type constructedClass = genericClass.MakeGenericType(t);
dynamic created = Activator.CreateInstance(constructedClass);
created.CB = new CB<int>();
created.CB.SetObject(0);
Console.ReadKey();
}
}
答案 2 :(得分:0)
通常,由于泛型是compile time
特性,因此您需要在编译时指定时间。
当你使用反射(运行时)时,你更喜欢使用基类型并使用polymorphism
来完成这样的事情。
我100%不理解你想做什么,但你可以:
1.在最坏的情况下使用ICallback<DeriveType>
并使用polymorphism
或object
(小心避免装箱\取消装箱值类型)。
2.创建一个非通用的界面,如下所示:
public interface ICallback {
void OnSuccess (DeriveType data);
void OnFailure (Exception exception);
}