Ищем шаблон для объединения частичных классов из разных сборок - PullRequest
2 голосов
/ 18 июля 2011

У меня следующая проблема. У меня есть основной проект и несколько дополнительных проектов с похожей функциональностью.

Например: у меня есть веб-сайт MVC, затем проект библиотеки классов «A» с «SettingsHelper». Это просто определяет статические оболочки для параметров конфигурации, чтобы их можно было использовать как свойства.

Затем у меня есть другой проект библиотеки классов "B", который также содержит "SettingsHelper class".

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

Я бы хотел иметь возможность подключать дополнительные библиотеки классов в один проект.

Ответы [ 5 ]

2 голосов
/ 18 июля 2011

Это не сработает.Частичные классы не могут быть разделены на сборки - они не существуют в CLR, только в редакторе и компиляторе.Таким образом, они скомпилированы вместе в один класс CLR.

То, что вы можете сделать, это наследовать одно от другого.Однако помощники, как правило, являются статическими классами, поэтому они тоже не будут работать.

Другой альтернативой является не написание вспомогательных классов, а методов расширения.Вы можете расширять классы в одной сборке с помощью методов, определенных в другой сборке (или нескольких других сборках).Смотри также http://msdn.microsoft.com/en-us/library/bb383977.aspx.

1 голос
/ 18 июля 2011

Звучит во многом как инъекция зависимости.Обычно вы выставляете SettingsHelper как интерфейс (ваш контракт) и программируете против этого.Затем DI-контейнер, такой как Ninject, StructureMap или Windsor, подключит реализацию этого интерфейса к соответствующим частям вашего кода на основе конфигурации.

Это позволит вам кодировать против известного контракта и предоставлять различныеВ зависимости от обстоятельств библиотеки DI могли бы затем использовать эту библиотеку для получения конкретной реализации интерфейса.

Нужны ли вам оба экземпляра одновременно?

Обратите внимание, что вы не можете использоватьключевое слово partial в разных сборках, только внутри сборки.

Обновление: на основе вашего комментария звучит так, как будто вы хотите сделать что-то вроде Composition.Имейте класс, который берет оба класса из любой библиотеки и объединяет их в один класс, который может использоваться вашим приложением.Независимо от того, настроите ли вы его для чего-то особенного или загрузите типы, когда библиотеки присутствуют, все это может быть инкапсулировано в этот новый класс.в MEF:

http://msdn.microsoft.com/en-us/library/dd460648.aspx

0 голосов
/ 19 июля 2011

Есть способ; Visual Studio позволяет включать один и тот же файл кода в несколько проектов.

Когда вы делаете «Добавить» / «Существующий элемент», вы можете выбрать файл, который находится в другой папке.

Это то, что делает некоторая поддержка silver light, чтобы разрешить «общий класс», который имеет некоторый метод, который только на сервере, и один метод, который только на клиенте.

(Что касается вопроса «хорошего дизайна», вам придется решить, что самим людям не нравится, когда один и тот же класс по-разному компилируется в разных проектах. # если XXX, когда XXX определен только в одном из проектов)

0 голосов
/ 18 июля 2011

Конкретный шаблон, который вам нужен, называется Фасадный шаблон .К сожалению, вы не получите никакой помощи от компилятора, который сделает это правильно.По существу:

  1. Создайте новый класс CombinedSettingsHelper в вашей локальной сборке.
  2. Если два типа SettingsHelper находятся в одном пространстве имен, вам необходимо настроить для них псевдонимы(проверьте справочные свойства в обозревателе решений и документацию MSDN для этого).
  3. Реализуйте объект так, чтобы он мог обращаться к обоим SettingsHelper объектам.

Чтобы очистить свой фасад, вы можете попробовать использовать абстрактный метод в соответствии с abstract object GetSettingValue(string name);.Ваш фасад может затем наследовать от того же базового класса и вызывать их для своих дочерних элементов.Например:

public abstract class SettingsHelperBase { public object GetSettingValue(string settingName); }

// Assembly1
public class SettingsHelper : SettingsHelperBase { }

// Assembly2
public class SettingsHelper : SettingsHelperBase { }

public class SettingsHelper : SettingsHelperBase
{
    private List<SettingsHelperBase> _backends = new List<SettingsHelperBase>();

    public readonly PropertiesImpl Properties;
    public class PropertiesImpl
    {
        private SettingsHelper _settingsHelper;
        public string Name
        {
            get
            {
                return (string)_settingsHelper.GetSettingValue("Name");
            }
        }

        internal PropertiesImpl(SettingsHelper helper)
        {
            _settingsHelper = helper;
        }
    }

    public SettingsHelper()
    {
        _backends.Add(asm1::MyNs.SettingsHelper);
        _backends.Add(asm2::MyNs.SettingsHelper);
        Properties = new PropertiesImpl(this);
    }

    protected override object GetSettingValue(string settingName)
    {
        foreach (var item in _backends)
        {
            var val = item.GetSettingValue(settingName);
            if (val != null)
                return val;
        }
        return null;
    }
}
0 голосов
/ 18 июля 2011

Я бы сказал, что переместите оба класса Helper в 3-й проект и добавьте ссылку , которую проект, в оба ваших проекта. Таким образом, эта новая библиотека станет общей библиотекой данных и функциональных возможностей .

Привет.

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