Как использовать переопределения сопоставления из многих сборок в генераторе FluentNhibernate AutoPersistenceModel - PullRequest
1 голос
/ 16 июля 2010

Можно ли настроить модель автоматического поддержания активности для чтения переопределений сопоставления и сопоставления из многих сборок.

В настоящее время я использую

public AutoPersistenceModel Generate()
        {
            var model =
                new AutoPersistenceModel()
                    .AddEntityAssembly(Assembly.GetAssembly(typeof(User)))
                    .Where(
                    this.GetAutoMappingFilter).Conventions.Setup(this.GetConventions()).Setup(this.GetSetup()).

                    UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();

            return model;
        }

        public AutoPersistenceModel Generate(params Assembly[] assemblies)
        {
            var model = this.Generate();
            assemblies.ToList().ForEach(x => model.AddEntityAssembly(x));

            return model;
        }

Проблема связана с

  UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();

, который занимает только одну сборку.Но я хотел бы собрать картографию и другие ее варианты из разных сборок.

Спасибо

Ответы [ 2 ]

2 голосов
/ 25 ноября 2012

Мы использовали несколько иной подход к решению этой проблемы с использованием версии FNH версии 1.3.x, имея в виду несколько конкретных целей проектирования:

  • Сохраняем наши доменные имена POCO.
  • Воспользуйтесь механизмом самосохранения FNH.
  • Пакет экземпляров IAutoMappingOverride в сборке с объектами, от которых они зависят.
  • Разрешить «плагин» для новых сборок, содержащих сопоставленные объекты, без необходимости изменения базовой конфигурации FNH.

Так же, как и решение OP, все наши отображенные сущности наследуются от набора известных базовых классов. Вооружившись этим и тем фактом, что AutoPersistenceModel.UseOverridesFromAssembly () действительно можно вызывать несколько раз, мы смогли внести простую модификацию в наш класс конфигурации автоматического сопоставления для динамического добавления переопределенных сборок:

internal sealed class SessionConfiguration : DefaultAutomappingConfiguration
{
    public AutoPersistenceModel PersistenceModel
    {
        get
        {
            Assembly[] assembliesToMap = MappedAssemblyResolver.GetMappedAssemblies();
            AutoPersistenceModel model = AutoMap.Assemblies(new SessionConfiguration(), assembliesToMap);

            foreach (Assembly potentiallyMapped in MappedAssemblyResolver.GetOverrideAssemblies(assembliesToMap))
            {
                model.UseOverridesFromAssembly(potentiallyMapped);
            }

            model.Conventions.AddFromAssemblyOf<SessionConfiguration>();
            // other FNH configuration options omitted

            return model;
        }
    }

    public override bool ShouldMap(Type type)
    {
        return type.IsSubclassOfRawGeneric(typeof(DomainObject<>));
    }
}

MappedAssemblyResolver выглядит примерно так:

internal static class MappedAssemblyResolver
{
    public static Assembly[] GetMappedAssemblies()
    {
        Assembly[] mappedAssemblies; 
        // TODO: implement your strategy for resolving assemblies

        return mappedAssemblies;
    }

    public static IEnumerable<Assembly> GetOverrideAssemblies(Assembly[] mappedAssemblies)
    {
        mappedAssemblies.CheckNull("mappedAssemblies");

        return mappedAssemblies;
    }
}

Несколько заметок:

  1. DomainObject является нашей сущностью базового домена. Он содержит общие вещи, такие как Id, DateCreated и т. Д.
  2. IsSubclassOfRawGeneric (Type) - это метод расширения, доступный здесь .
  3. CheckNullOrEmpty (string) - метод расширения, доступный здесь .
  4. Вам потребуется реализовать способ фактического разрешения ваших сборок в GetMappedAssemblies (). Мы проводим некоторую проверку AppDomain.CurrentDomain, и они применяют некоторые правила, чтобы определить, какие сборки мы считаем соответствующими.

Также обратите внимание, что, хотя мы помещаем экземпляры IAutoMappingOverride в ту же сборку, что и наши объекты, вы можете легко изменить реализацию GetOverrideAssemblies (Assembly []), если ваша цель заключалась в дальнейшем отделении вашего домена от FNH.

В любом случае, это должно позволить вам добавлять новые сопоставленные сущности (или новые содержащие их сборки) и связанные с ними переопределения сопоставления по желанию, не задумываясь об их добавлении в базовую FNH AutoPersistenceModel.

1 голос
/ 13 октября 2010

Таким образом, проблема с .UseOverridesFromAssemblyOf в том, что они не дублируют тип.

Код взят из FluentNHibernate:

public AutoPersistenceModel UseOverridesFromAssembly(Assembly assembly)
    {
      this.alterations.Add(new AutoMappingOverrideAlteration(assembly));
      return this;
    }
public AutoMappingAlterationCollection Add(IAutoMappingAlteration alteration)
    {
      if (!this.alterations.Exists(a => a.GetType() == alteration.GetType()))
      {
        this.alterations.Add(alteration);
      }
      return this;
    }

Вы можете видеть, что добавление дублированного типа запрещено.

После изучения кода FNH я обнаружил, что они, наконец, изменяют AutoMappingOverrideAlteration, и я просто пишу расширение, чтобы применить это изменение

 public static class AutoPersistenceModelExtension
    {
        public static AutoPersistenceModel AddMappingAssembly(this AutoPersistenceModel model, Assembly assembly)
        {
            new AutoMappingOverrideAlteration(assembly).Alter(model);
            return model;
        }

        public static AutoPersistenceModel AddMappingFromAssemblyOf<T>(this AutoPersistenceModel model)
        {
            return model.AddEntityAssembly(typeof (T).Assembly);
        }


    }

Результат: Наше приложение построено на основе компонентов, каждый из которых предоставляет свои сущности и сопоставления для этих сущностей. Каждый компонент должен быть производным от класса BaseComponent, который имеет абстрактный метод для изменения модели.

Ex of FulfillmentModuleRegistration:

public override void AddToModel(AutoPersistenceModel autoPersistenceModel)
        {
            autoPersistenceModel.AddEntityAssembly(typeof(SupplierListItem).Assembly);
            autoPersistenceModel.AddMappingFromAssemblyOf<SupplierListItemMappingOverride>();
        }

и наши global.asax.cs:

 var autoPersistenceModel = new AutoPersistenceModelGenerator().Generate();
            //TODO: Refactor this, instead of instantiate each module we have to go thought a list of loaded module and apply their model alteration
            new QuestionBankModuleRegistration().AddToModel(autoPersistenceModel);
            new FulfilmentServiceAreaRegistration().AddToModel(autoPersistenceModel);

            var cfg = NHibernateSession.Init(
                this.webSessionStorage,
                new[] { this.Server.MapPath("~/bin/baseMappings.dll") },
                autoPersistenceModel,
                this.Server.MapPath("~/Hibernate.cfg.xml"));

baseMappings.dll содержит наши базовые объекты, такие как: пользователи, поисковые запросы и т. Д. Таким образом, это может быть любая сборка, которая содержит базовые, сопоставления по умолчанию, соглашения и т. Д.

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