Статически производный тип в C #? - PullRequest
2 голосов
/ 02 января 2012

Я ищу C # альтернативу C ++ typedefs или классам черт в конкретном случае. Я знаю, что нет прямых эквивалентов, но, возможно, есть некоторые альтернативные решения для этой конкретной проблемы?

Вот что я пытаюсь сделать. Я пишу рамки, где есть три связанных типа. Вид, резервное хранилище и фабрика. Будет несколько реализаций всех трех интерфейсов. Между представлением и фабрикой существует соотношение 1-1, а между представлением и хранилищем - 1-N. Конкретный импл. фреймворка выглядит примерно так:

Storage : IStorage<int> ...

View : IView<Storage> ... // And IView<T> : IViewNonGeneric further up..

Factory : IFactory<Storage> {
  // This needs to take a concrete storage type as arg
  IViewNonGeneric CreateView(Storage s) ... 

  Storage CreateStorage() ...  
}

Класс View является наиболее важным классом для пользователей платформы; остальные - это детали реализации. Из-за этого казалось бы более естественным определять Фабрику в терминах класса View (а не в терминах Storage). В C ++ это было бы просто, просто добавьте typedef к представлению и используйте его на фабрике, например, так:

class IView<typename T> { typedef T TStorage; ...

class IFactory<typename T> { 
  IViewNonGeneric CreateView(typename T::TStorage s) ... 

В C # у нас явно нет классов typedefs или traits. Есть ли другой способ добиться желаемого эффекта? То есть можно ли использовать View как универсальный параметр для Factory и получить конкретный тип Source из View?

Ответы [ 2 ]

3 голосов
/ 02 января 2012

Обобщения в C # определенно не так мощны, как шаблоны в C ++.Однако в C # есть нечто очень мощное, чего нет в C ++: Reflection.

Должно быть очень легко определить метод (статический или экземпляр) в классе представления, который бы возвращал конкретный тип хранилища.учебный класс.Затем вы можете использовать Type.GetConstructor для динамического поиска конструктора класса хранения и вызова его с помощью метода ConstructorInfo.Invoke.

Кроме того, вы можете изучить использование пользовательских атрибутов, которые вы можете назначить вашему классу представления.Как насчет чего-то вроде этого:

[StorageType( typeof( MyStorage1 ) ]
class MyView1 { ... }

Затем используйте отражение для typeof (MyView1), чтобы увидеть, не связано ли с ним StorageTypeAttribute.

0 голосов
/ 06 декабря 2013

Я думаю, что вы хотите:

public interface IStorage<T>
{
}

public class IntStorage : IStorage<int>
{
}

public interface IFactory<S, T> where S : IStorage<T>
{
    IView<S, T> CreateView(S storage);
}

public interface IViewNonGeneric
{
}
public interface IView<S, T> : IViewNonGeneric where S : IStorage<T>
{
}

public class IntView : IView<IntStorage, int>
{
}

public class IntFactory : IFactory<IntStorage, int>
{
    public IntView CreateView(IntStorage storage)
    {
        // create the view
    }
    // private interface implementation
    IView<IntStorage, int> IFactory<IntStorage, int>.CreateView(IntStorage storage)
    {
        return CreateView(storage);
    }
}

...
...