Присвоение имен свойствам во время компиляции в универсальном классе

#c# #generics #reflection

#c# #общие #отражение

Вопрос:

Я пытаюсь написать универсальный класс, передать ему некоторые типы, а затем получить к нему доступ через свойства.

Я написал этот код:

 class Factory<T1, T2> where T1 : Test, new()
                      where T2 : Test, new()
{
    public T1 FirstType { get; set; }
    public T2 SecondType { get; set; }

    public Factory() 
    {
        FirstType = new T1();
        SecondType = new T2();
    }
}
  

и я использую это так (OtherTest реализует тест):

 Factory<Test, OtherTest> factory = new Factory<Test, OtherTest>();
factory.FirstType.MyMethod();
  

Затем я могу использовать свойства FirstType и SecondType, однако, если я изменю порядок:

 Factory<OtherTest, Test> factory2 = new Factory<OtherTest, Test>();
  

Это будет иметь другое поведение, поскольку FirstType будет OtherTest . Я хотел бы передавать экземпляры и иметь возможность писать такой код:

 Factory<Test, OtherTest> factory = new Factory<Test, OtherTest>();
factory.Test.MyMethod();    //I want to generate properties named after class
factory.OtherTest.MyMethod();
  

Могу ли я сделать это во время компиляции?

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

1. Боюсь, я не совсем понимаю, в чем заключается ваш вопрос. Все в порядке до тех пор, пока » Я хотел бы передавать экземпляры и иметь возможность писать такой код… Могу ли я сделать это во время компиляции? «, и, боюсь, я понятия не имею, что вы пытаетесь сделать во время компиляции.

2. У меня есть очень наглядный пример. Я хочу создать фабрику Factory<A, B> factory = new Factory<A, B>(); , а затем получить доступ к ее полям по имени классов (A, B). Я в основном хочу переименовать FirstType / SecondType в имена типов T1, T2 (A, B или Test, OtherTest).

3. Правильно. Нет, вы не можете этого сделать.

4. Не во время компиляции, нет.

5. Вы могли бы взглянуть на генерацию кода и текстовые шаблоны T4 .

Ответ №1:

Вы не можете изменять имена свойств с помощью параметров универсального типа. Самое близкое, что вы можете получить, — это словарь

 Dictionary<string, Test> Tests;
  

Затем вы можете использовать typeof(T1).Name и nameof для безопасного предоставления имен свойств.

 Tests.Add(typeof(T1).Name, new T1());

Test test = Tests[nameof(FirstType)];
  

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

1. Действительно ли нет способа обернуть Tests[nameof(FirstType)]; во что-то вроде Tests.FirstType; или Tests.Get(FirstType); ?

2. @e.e, как все до сих пор говорили, нет. Это не то, что поддерживают дженерики C #.

3. Ну, вы можете использовать dynamic тип C # и класс ExpandoObject . Но он разрешает имена во время выполнения и не является типобезопасным.