Фабрики класса C # - PullRequest
       3

Фабрики класса C #

5 голосов
/ 15 марта 2011

У меня есть класс с именем Foo, у которого есть функция, которая выглядит следующим образом

List<Bar> LoadData();

И Foo, и Bar находятся в библиотеке, которую я хочу использовать в других проектах. Сейчас я работаю над новым проектом и хочу создать подкласс Bar. Давайте назовем это NewBar.

Каков простой и гибкий способ получения Foo.LoadData для возврата списка NewBar? Я думаю, что нужна фабрика или, возможно, просто функция делегата. Кто-нибудь может привести пример?

Спасибо, Энди

Ответы [ 6 ]

3 голосов
/ 15 марта 2011

Может быть, даже проще, зависит от того, что вам нужно, но общих ограничений может быть достаточно, если Bar создается с помощью конструктора без параметров:

public List<TBar> LoadData<TBar>()
    where TBar : Bar, new()
{
    // return a list populated with `new TBar()`;
}

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

var newBars = Foo.LoadData<NewBar>();
2 голосов
/ 15 марта 2011

Самым простым способом было бы реализовать интерфейс, реализованный в Bar и NewBar, и вместо этого сделать так, чтобы ваша функция возвращала List<IBar>.

Это так или возвращала object и приводила в изобилии.

1 голос
/ 15 марта 2011

Здесь есть несколько проблем.Поскольку вы используете List<Bar>, это не сработает, если вы вернете List<Baz>, поскольку List<> не выполняет ковариацию .

.сделайте это virtual, чтобы в новом проекте создать SubFoo, и вы можете вернуть IEnumerable<Baz>.


ОБНОВЛЕНИЕ

ОК, согласно предоставленной вами новой информации ( вы используете его для заполнения списка из XML ), я бы создал virtual protected CreateBar(), который создает новый объект bar и вызывается LoadData () для создания нового Bar в цикле.В SubFoo я переопределяю и возвращаю Baz вместо этого.В SubFoo я позвоню base.LoadData() и заполню список Baz, а затем добавлю логику для заполнения новых свойств Baz, которых нет в Bar.

Или, возможно,

просто используйте XML Serilization, и я получаю все это бесплатно!

1 голос
/ 15 марта 2011

Сделать LoadData() виртуальным.Затем переопределите его в производной фабрике.

Если метод производной фабрики будет по-прежнему возвращать список Bar, но вы можете указать в реализации метода, что все экземпляры Bar на самом деле NewBar,Это можно изменить с помощью универсального метода, как в примере Snowbear.

0 голосов
/ 15 марта 2011

Прочитав ответы (спасибо!) Я придумал следующее. Почему это не очень хорошая идея?

public interface IBarFactory
{
    Bar Create();
}

Затем измените LoadData на:

List<Bar> LoadData(IBarFactory Factory)
{
    List<Bar> MyList = new List<Bar>();

    if (Factory == null)
    {
        MyList.Add(new Bar());
    }
    else
    {
        MyList.Add(Factory.Create());
    }

    // etc, etc
}

Тогда мне просто нужно создать следующее:

public class BazFactory : IBarFactory
{
    Bar Create() { return new Baz() };
}

Наконец, назовите это:

MyList = LoadData(BazFactory);
0 голосов
/ 15 марта 2011

Пришло время узнать о ковариации и контравариантности.Это не маленькая вещь, чтобы учиться.По сути, я бы предложил создать IBar Interfarce, это сделает вашу жизнь намного проще.

Прочтите о концепциях msdn , но вы должны продолжать искать и другие примеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...