Как мне сохранить ссылку на универсальный тип, созданный на основе выражения, переданного методу?

#c# #generics #expression

#c# #общие #выражение

Вопрос:

У меня есть следующий метод, который возвращает универсальный объект типа INamedProperty<TReturn> на основе возвращаемого типа определенного выражения. Мне нужно сохранить ссылку на объект, который возвращается этим методом для будущей обработки. В каком типе я должен его сохранить? Object Было бы нормально? Как я мог бы привести его к соответствующему INamedProperty<TReturn> позже? Нужно ли мне также сохранять тип TReturn ?

 public class PropertyBuilder<T> : IPropertyBuilder<T> where T : class {
    public INamedProperty<TReturn> Named<TReturn>(Expression<Func<T, TReturn>> property) {
        o = new NamedProperty<TReturn>();
        // how do I store o as an instance of the encapsulating class?
    }
}
  

Заранее спасибо!

Комментарии:

1. Я предполагаю, T является аргументом типа для заключающего класса?

2. Да. Извиняюсь, что не уточнил это. Я приведу еще немного контекста в своем вопросе.

3. Как вы будете использовать этот объект в будущей обработке? Если ссылки на объект достаточно, просто используйте это. Что произойдет, если именованный универсальный метод вызывается сначала как Named<A> , затем как Named<B>?

Ответ №1:

Я бы попытался реализовать универсальный, неуниверсальный INamedProperty , который мог бы реализовать необходимые вам операции:

 interface INamedProperty
{
    // Informational
    Type ContainingType { get; }
    string Name { get; }
    Type ReturnType { get; }

    // Operations (for example)
    void CopyTo(object obj, INamedProperty property);
}
  

Затем реализуйте их в универсальном NamedProperty:

 class NamedProperty<T> : INamedProperty { ... }
  

Комментарии:

1. Это то, к чему я в итоге пришел. Спасибо за ввод!

Ответ №2:

Почему бы не использовать дополнительный параметр действия вместо сохранения ссылки? Вы сталкиваетесь с проблемой, потому что TReturn на самом деле не существует в конкретной форме вне контекста выполнения вашего метода; подумайте о более функциональном программировании и менее процедурном.

редактировать: добавлен пример кода

 public INamedProperty<TReturn> Named<TReturn>(Expression<Func<T, TReturn>> property, Action<INamedProperty<TReturn>> action)
{
    var o = new NamedProperty<TReturn>();
    action.Invoke(o);
    return o;
}
  

Комментарии:

1. Не могли бы вы подробнее остановиться на этом, пожалуйста?

2. Вы знаете, что C # позволяет вам просто вызывать делегатов, вам не нужно использовать Invoke() ? например: action(o); , ret = func(a); .