Страницы

Поиск по вопросам

воскресенье, 12 января 2020 г.

Возможно ли создать интерфейс для создания экземпляра одного из следующих классов?

#c_sharp #проектирование #шаблоны_проектирования


Добрый день! Пусть есть несколько классов, например:

public class ProductA 
{
   public string FieldFirst { get; set; }
   public string FieldSecond { get; set; }
   public string FieldThird { get; set; }
   public string FieldFourth { get; set; }
}

public class ProductB 
{
   public string FieldFirst { get; set; }
   public string FieldSecond { get; set; }
   public string FieldThird { get; set; }
   public List FieldFourth { get; set; }
}

public class ProductC 
{
   public string FieldFirst { get; set; }
   public string FieldSecond { get; set; }
   public List FieldThird { get; set; }
}

public class ProductD 
{
   public string FieldFirst { get; set; }
   public List FieldSecond  { get; set; }
}


Собственно, хотел узнать, возможно ли сделать общий интерфейс для выбора класса и
создания объекта. Нельзя ли найти какой-нибудь единый  интерфейс для них, и использовать,
например  Абстрактную Фабрику. Или это нельзя сделать в данном случае. Заранее огромное
спасибо! 
    


Ответы

Ответ 1



Простое решение Если типы аргументов известны на стадии компиляции и наборы типов параметров уникальны, то можно сделать банальную фабрику: public static class ProductFactory { public static ProductA Create (string fieldFirst, string fieldSecond, string fieldThird, string fieldFourth) { return new ProductA(fieldFirst, fieldSecond, fieldThird, fieldFourth); } public static ProductB Create (string fieldFirst, string fieldSecond, string fieldThird, List fieldFourth) { return new ProductB(fieldFirst, fieldSecond, fieldThird, fieldFourth); } public static ProductC Create (string fieldFirst, string fieldSecond, List fieldThird) { return new ProductC(fieldFirst, fieldSecond, fieldThird); } public static ProductD Create (string fieldFirst, List fieldSecond) { return new ProductD(fieldFirst, fieldSecond); } } Тогда создание объектов будет выглядеть следующим образом: ProductA productA = ProductFactory.Create("1", "2", "3", "4"); ProductD productD = ProductFactory.Create("1", new List()); Здесь я предположил следующие классы продуктов: public class ProductA { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public string FieldThird { get; set; } public string FieldFourth { get; set; } public ProductA (string fieldFirst, string fieldSecond, string fieldThird, string fieldFourth) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; FieldFourth = fieldFourth; } } public class ProductB { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public string FieldThird { get; set; } public List FieldFourth { get; set; } public ProductB (string fieldFirst, string fieldSecond, string fieldThird, List fieldFourth) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; FieldFourth = fieldFourth; } } public class ProductC { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public List FieldThird { get; set; } public ProductC (string fieldFirst, string fieldSecond, List fieldThird) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; } } public class ProductD { public string FieldFirst { get; set; } public List FieldSecond { get; set; } public ProductD (string fieldFirst, List fieldSecond) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; } } Сложное решение Если на стадии компиляции ничего не известно, а аргументы собираются вручную во время выполнения программы, то можно воспользоваться Autofac, например. Вот пример использования, когда выбор делается на основе имён и типов параметров, и имена параметров не совпадают с именами аргументов конструктора: var builder = new ContainerBuilder(); builder .Register((c, p) => { switch (p.Count()) { case 4: if (p.OfType().Any(a => a.Name == "str4")) return new ProductA( p.Named("str1"), p.Named("str2"), p.Named("str3"), p.Named("str4")); else return new ProductB( p.Named("str1"), p.Named("str2"), p.Named("str3"), p.Named>("ints")); case 3: return new ProductC( p.Named("str1"), p.Named("str2"), p.Named>("doubles")); case 2: return new ProductD( p.Named("str1"), p.Named>("floats")); } throw new DependencyResolutionException("Could not resolve product."); }) .As(); IContainer container = builder.Build(); var productA = container.Resolve( new NamedParameter("str1", "1"), new NamedParameter("str2", "2"), new NamedParameter("str3", "3"), new NamedParameter("str4", "4")); var productD = container.Resolve( new NamedParameter("str1", "1"), new NamedParameter("floats", new List())); Предполагается, что продукты реализованы следующим образом: public interface IProduct {} public class ProductA : IProduct { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public string FieldThird { get; set; } public string FieldFourth { get; set; } public ProductA (string fieldFirst, string fieldSecond, string fieldThird, string fieldFourth) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; FieldFourth = fieldFourth; } } public class ProductB : IProduct { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public string FieldThird { get; set; } public List FieldFourth { get; set; } public ProductB (string fieldFirst, string fieldSecond, string fieldThird, List fieldFourth) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; FieldFourth = fieldFourth; } } public class ProductC : IProduct { public string FieldFirst { get; set; } public string FieldSecond { get; set; } public List FieldThird { get; set; } public ProductC (string fieldFirst, string fieldSecond, List fieldThird) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; FieldThird = fieldThird; } } public class ProductD : IProduct { public string FieldFirst { get; set; } public List FieldSecond { get; set; } public ProductD (string fieldFirst, List fieldSecond) { FieldFirst = fieldFirst; FieldSecond = fieldSecond; } }

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

Отправить комментарий