2012-05-23 2 views
3

Я нахожусь в процессе создания фабричного метода, который использует общий абстрактный тип типа, чтобы возвращать экземпляр конкретного производного типа с использованием отражения. Напр.Метод Generic Factory для создания производного класса из базового класса

public abstract class ServiceClientBase : IServiceClient 
{ 
} 

public abstract class Channel : ServiceClientBase 
{ 
} 

public class ChannelImpl : Channel 
{ 
} 

public class ServiceClientFactory 
{ 
    public T GetService<T>() where T : class, IServiceClient 
    { 
     // Use reflection to create the derived type instance 
     T instance = typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null).Invoke(new object[] { endPointUrl }) as T; 
    } 
} 

Использование:

Channel channelService = factory.GetService<Channel>(); 

Проблема в том, что я не могу понять, какой-либо элегантный способ для фабричного метода для создания экземпляра производного типа передается абстрактный базовый тип в методе. Единственное, что я могу придумать, это поддерживать словарь, содержащий карту между абстрактной базой и соответствующим производным классом, но это кажется мне как запах кода. Может ли кто-нибудь предложить лучшее решение.

+0

Ну, предположим, у вас было две различные конкретные реализации абстрактного класса - как бы вы хотели принять решение тогда? –

+0

Это точно моя забота. Только в моем конкретном случае я знаю, что будет только одна конкретная реализация. Но все же я искал более элегантный способ решения проблемы. – koder

+0

Вы пытаетесь создать прокси-сервер WCF? Меня интересовал бы полный контекст, потому что вы можете попытаться воссоздать колесо. – Bronumski

ответ

4

Хотя вы уверены, что существует только одна реализация, и если предположить, что она находится в пределах одной сборки, вы можете найти ее через отражение. Например:

Type implementationType = typeof(T).Assembly.GetTypes() 
            .Where(t => t.IsSubclassOf(typeof(T)) 
            .Single(); 
return (T) Activator.CreateInstance(implementationType); 

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

Если существует несколько классов реализации, вам нужно подумать об альтернативе - один из вариантов был бы атрибутом абстрактного класса, говорящим, какую реализацию использовать, если это возможно. (Трудно дать хорошие варианты без дополнительного контекста.)

1

Вы, кажется, пытаетесь изобрести контейнер IOC. Посмотрите, например, на Autofac. Вы регистрируете свои конкретные типы с контейнером IOC, а затем запрашиваете их по интерфейсу.

+0

. На самом деле это может быть целесообразным вариантом. Я просто работал над POC. Итак, я пытался найти удобную альтернативу. Я бы определенно подумал об использовании IOC для разрешения зависимости. – koder