2014-09-28 4 views
1

меня есть интерфейсИспользуя общий C# интерфейс как класс собственности

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 собственности. Я не хочу специализировать свойство, потому что я не знаю тип. Тип определяется во время выполнения через отражение.

Вот небольшое объяснение того, что происходит:

  1. Класс прокси генерируется (с помощью CreateInterfaceProxyWithoutTarget<C> из Castle DynamicProxy) во время выполнения для реализации данного интерфейса (Давайте назовем это IModel)
  2. Вызова (помните, что нет цели, поэтому здесь нет кода, который выполняется здесь, кроме того, что делает мой перехватчик)
  3. Вызов метода перехватывается основным классом, который решает, что нужно делать на основеатрибуты метода и его параметры (как определено в IModel)
  4. На данный момент, если последний параметр перехваченного метода является ICallback<T>, он получает назначение на Callback собственности, в противном случае это null.
  5. Если обратный вызов не null, результат операции разобран и вызывается соответствующий метод обратного вызова.

Это то, что класс перехватчик выглядит следующим образом:

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#, и я погружаюсь глубоко в C# после 4 лет не касаясь его. Будьте любезны!

+0

что, если 'Callback' свойство не * автоматически генерировать * и' Set' это с 'ServisFactory'? –

ответ

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(); 
    } 
} 
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;} 
} 
0

Вообще, поскольку дженериков является compile time особенность, вам нужно будет указать время во время компиляции.

Когда вы используете отражение (время выполнения), вы предпочитаете работать с базовыми типами и использовать polymorphism для выполнения таких задач.

Я не понимаю, на 100%, что вы хотели сделать, но вы можете:

1.Use в ICallback<DeriveType> и работать с polymorphism или object в худшем случае (будьте осторожны, чтобы избегайте бокса \ распаковка типов значений).

2.Create нераскрытый общий интерфейс, который будет выглядеть примерно так:

public interface ICallback { 
    void OnSuccess (DeriveType data); 
    void OnFailure (Exception exception); 
} 
Смежные вопросы