Как добавить сопоставления по пространству имен в Fluent NHibernate - PullRequest
8 голосов
/ 01 июня 2011

В моем приложении мне нужно общаться с несколькими базами данных.Я обрабатываю это в NHibernate, создавая один SessionFactory для каждой базы данных (я полагаю, что это правильно).Итак, у меня есть два набора моделей (по одному на базу данных) и два набора отображений Fluent NHibernate ClassMap<>.Оба находятся в одном и том же проекте (разделены пространством имен), и я бы хотел оставить его таким.

Проблема возникает при создании SessionFactory.Насколько я вижу, в Fluent NHibernate есть два основных способа добавления сопоставлений:

    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserClassMap>())
    .Mappings(m => m.FluentMappings.Add<UserClassMap>()

Если я использую первую перегрузку, то мои сеансовые фабрики получают все сопоставления для обеих баз данных.Если я использую второе, я должен указать каждый отдельный ClassMap.Я хотел бы что-то вроде FluentMappings.AddFromNamespace().Есть ли способ сделать это?

Ответы [ 4 ]

16 голосов
/ 02 июня 2011

Странно, что FluentNHibernate поддерживает этот тип фильтрации для автоматического сопоставления, но не для ClassMap s.Не должно быть слишком сложно добавить эту функцию самостоятельно, используя магию методов расширения.Попробуйте это:

public static FluentMappingsContainer AddFromAssemblyOf<T>(
    this FluentMappingsContainer mappings,
    Predicate<Type> where)
{
    if (where == null)
        return mappings.AddFromAssemblyOf<T>();

    var mappingClasses = typeof(T).Assembly.GetExportedTypes()
        .Where(x => (typeof(IMappingProvider).IsAssignableFrom(x)
                || typeof(IExternalComponentMappingProvider).IsAssignableFrom(x))
            && where(x));

    foreach (var type in mappingClasses)
    {
        mappings.Add(type);
    }

    return mappings;
}

... и используйте это так:

m.FluentMappings.AddFromAssemblyOf<UserClassMap>(t => t.Namespace.StartsWith("One.Of.The.Two.Namespaces"));
10 голосов
/ 02 июня 2011

Я закончил писать метод расширения, который делает это для меня.В основном он использует рефлексию, чтобы перебрать все интересующие меня типы и добавить их один за другим.Он основан на реализации AddFromAssemblyOf.Использование:

.Mappings(m => m.FluentMappings.AddFromNamespaceOf<UserClassMap>())

Реализация:

public static class FluentNHibernateExtensions
{
    public static FluentMappingsContainer AddFromNamespaceOf<T>(
        this FluentMappingsContainer fmc)
    {
        string ns = typeof(T).Namespace;
        IEnumerable<Type> types = typeof(T).Assembly.GetExportedTypes()
            .Where(t => t.Namespace == ns)
            .Where(x => IsMappingOf<IMappingProvider>(x) ||
                        IsMappingOf<IIndeterminateSubclassMappingProvider>(x) ||
                        IsMappingOf<IExternalComponentMappingProvider>(x) ||
                        IsMappingOf<IFilterDefinition>(x));

        foreach(Type t in types) {
            fmc.Add(t);
        }

        return fmc;
    }

    /// <summary>
    /// Private helper method cribbed from FNH source (PersistenModel.cs:151)
    /// </summary>
    private static bool IsMappingOf<T>(Type type)
    {
        return !type.IsGenericType && typeof(T).IsAssignableFrom(type);
    }
}

Предостережения:

  • Имя немного вводит в заблуждение, поскольку оно ищет только одну сборку.Возможно, его следует назвать AddFromAssemblyAndNamespaceOf, но это немного многословно.
  • Это не совсем будущее.Если в будущих версиях FNH будут добавлены или удалены некоторые из сопоставляемых интерфейсов, они не будут включать их.

Но это работает для моих целей.

0 голосов
/ 01 июня 2011
... AutoMap.AssemblyOf<Person>().Where(x => x.Namespace.EndsWith("Domain")) ...
0 голосов
/ 01 июня 2011

Нет способа сделать это.Я рекомендую разделить пространства имен на отдельные проекты.Помните:

Отдельные пространства имен, тот же проект, когда логическое разделение имеет смысл.Отдельные пространства имен, отдельные проекты, когда физическое разделение имеет смысл.

В этом случае, поскольку вы не можете разделить пространство имен в отображениях nhibernate, физическое разделение имеет смысл.Однако вы можете обойти это с помощью быстрых автоматов, которые используют конфигурацию .Where или ShouldMap.Найдите беглых автоматов и посмотрите, сможет ли это привести вас туда, куда вы хотите.

...