Страницы

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

суббота, 9 марта 2019 г.

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

Добрый день! Пусть есть несколько классов, например:
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; } }
Собственно, хотел узнать, возможно ли сделать общий интерфейс для выбора класса и создания объекта. Нельзя ли найти какой-нибудь единый интерфейс для них, и использовать, например Абстрактную Фабрику. Или это нельзя сделать в данном случае. Заранее огромное спасибо!


Ответ

Простое решение
Если типы аргументов известны на стадии компиляции и наборы типов параметров уникальны, то можно сделать банальную фабрику:
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; } }

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

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