Splitting configuration in Fluent NHibernate - fluent-nhibernate

I am trying to split the configuration in Fluent NHibernate between two classlibraries (dll's).
The first classlibrary would configure certain listeners in NHibernate (for auditing and security) and the second would map/automap the entities. Any good ideas for how to pass the Fluent config between the libraries?
One idea I have is using Castle Windsor (part of my infrastructure already) and installers to pass the config via the container between the libraries. Does that sound reasonable?

i have a similar scenario where configure the mappings somewhere else. I dont pass the config around, i just take the mappings as a whole from different providers.
For example:
Fluently.Configure()
.Mappings(m => m.AutoMappings.Add(Container.Resolve<IAutoMapProvider>().Get())
public class AutoMapProvider : IAutomapProvider
{
...
public static AutoPersistenceModel Get()
{
return AutoMap
.AssemblyOf<MyObjectBase>(new MyConfiguration())
.IgnoreBase<MyObjectBase>()
.Conventions.Setup(c =>
// ...
}
}

Related

AutoMapper not detecting profiles in external assemblies

I am using ASP.Net core with latest Automapper. This is related to this and this. I think I am doing what needs to be done according to those questions, but still I get below error from Automapper.
AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
ToDoDto -> CreateTodoCommand
Module.Todo.Domain.Dto.ToDoDto -> Module.Todo.Domain.Commands.CreateTodoCommand
at lambda_method19(Closure , ToDoDto , CreateTodoCommand , ResolutionContext )
I have an interface which will be implemented by classes that needs to participate in mappings.
public interface IMapFrom<T>
{
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
But mapping classes can be in many assemblies since I have a plugin architecture. So, lot of stuff are being loaded dynamically by the host application. My Assembly locating method use below line to load Assembly in a loop until it finishes loading all modules.
AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName); //file.FullName is full path to Dll like E:\Project\Modules\Module.Todo\bin\Module.Todo.dll
Once it's done I can see loaded assemblies in watch window
Above loading method gets called in ConfigureServices(). I know this should work because the same assembly collection is passed to MediatR services.AddMediatR(assemblies) as well as Automapper services.AddAutoMapper(assemblies);
MediatR scans and find all Commands etc. but Automapper fails to locate mappings from other assemblies. However Automapper loads profiles properly from directly linked assemblies via Assembly.GetExecutingAssembly().GetReferencedAssemblies()
What may be the problem?
I got my assemblies to load properly and setup the mappings to work by making my mappings by inheriting Profile class like
public class MyProfile:Profile
{
public MyProfile()
{
CreateMap<A,B>();
}
}
and not using
public interface IMapFrom<T>
{
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}

How do I auto-register/resolve services by their interface?

I'm developing a MVC .NET Core 3/Angular/Entity Framework application. My application will likely have a lot of repositories in it. To support this I would like to resolve the service (repository) by its default interface (i.e. I request IRepository and the DI resolver gives me Repository). I know I can manually wire up the dependencies, but all of my DI frameworks in the past have had a means of auto-registering/resolving based on patterns or the like.
For example, with Castle Winsdor I could wire it up like this:
container.Register(Classes
.FromAssemblyNamed("MyLibary.Repository")
.InNamespace("MyLibrary.Repository")
.WithService.DefaultInterfaces()
.LifestyleTransient()
);
This would register all classes in the MyLibrary.Repository namespace to be resolved by their default interfaces they implement. How can this be done in .NET Core 3? If this isn't built-in, I'm assuming I will have to use reflection to query all the classes in the assembly, iterate through each class and register it by its interface it implements.
I would recommend AutoRegisterDI lib to not reinvent a bicycle. It's fast, simple and based on Microsoft Dependency Injection. This benchmark will show you the speed difference.
And this is the article about how to use it
Install this package:
NetCore.AutoRegisterDi
Add this code to your program.cs:
builder.Services.RegisterAssemblyPublicNonGenericClasses()
.Where(c => c.Name.EndsWith("Service"))
.AsPublicImplementedInterfaces(ServiceLifetime.Scoped); // default is Transient
If you have a Singleton service , add [RegisterAsSingleton] on top of your service class.
If you want to ignore injection of an particular interface add this line after .Where() :
.IgnoreThisInterface<IMyInterface>()
you can do this with reflection in c#.first create an extension method like this :
public static void AddScopedServices(this IServiceCollection serviceCollection)
{
}
and use it in startup.cs ,ConfigureServices method : services.AddScopedServices();
now to implement this method like this:
var allProviderTypes = System.Reflection.Assembly.GetAssembly(typeof(ICartRepository))
.GetTypes().Where(t => t.Namespace != null).ToList();
foreach (var intfc in allProviderTypes.Where(t => t.IsInterface))
{
var impl = allProviderTypes.FirstOrDefault(c => c.IsClass && intfc.Name.Substring(1) == c.Name);
if (impl != null) serviceCollection.AddScoped(intfc, impl);
}
you just need to put all your interfaces in a namespace and introduce one of them in this method ,in my case I used ICartRepository ,so it takes all interfaces and search for classes which inherit from that interface.
one point you need to consider is that class names must be like interfacenames without 'I' in the beginning ,like 'CartRepository'
I recently got tired of writing the same old
services.AddTransient<IInterface,IImplementation>
so I created a simple library to help me auto-register services.
You can check it out here.
Register the library in Startup.cs
There are 3 interface -> ITransient, IScoped, ISingleton generic and non-generic versions.
Let's say you want to register service "TestService" as transient.
TestService: ITransient<ITestService>, ITestService
Inherit ITransient interface and its done.
For more detailed information please refer to the Readme section.
Currently it lacks registering services with implementation factory, but it's something I'm willing to do in the near future.

Lost scope using DependencyResolver in another class library, using Castle Windsor and FluentNhibernate and NHibernate

In my WCF project I register my interface using Castle Windsor in the global.asax:
Component.For<IStrategy>()
.ImplementedBy<MyStrategy>()
.LifestylePerWcfOperation(),
Then later on in the same file I configure NHibernate using FluentNhibernate using a provider:
FluentConfiguration configuration = Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2008.ConnectionString(myConnString)
.Provider<ConnectionProvider>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<TenantMap>()) etc etc
However this ConnectionProvider is hosted in a common shared dll library as there are other WCF services that need to use it. I want to register this dependency as below but it doesn't work which means I have to manually new up a instance.
public ConnectionProvider()
{
// doesnt work
using (IDependencyScope scope = GlobalConfiguration.Configuration.DependencyResolver.BeginScope())
{
_myStrategy = scope.GetService<IStrategy>();
}
}
Is there anyway to make this work? Its like its lost scope as its in another assembly now. In the same assembly the DependencyScope works fine and creates an instance, but I want to keep it in a shared dll.
EDIT: The error I get is "System.Web.Http.Dependencies.EmptyResolver" on a watch on this bit of code: GlobalConfiguration.Configuration.DependencyResolver
I can see several problems with the code above:
1) You are registering IStrategy,MyStrategy with a per WcfOperation lifestyle. This means that windsor will create a strategy for each WcfOperation. On the otherhand you are trying to manually set the lifestyle of the component by using scope.GetService. For scope.GetService to work you will need a lifestyle scoped.
2) Assuming that the code for ConnectionProvider above is the constructor, it seems that the constructor is trying to get something from the container. This is in general a bad idea, and even worse when using an Ioc container like windsor. Instead pass the IStrategy to the constructor (inject it).
3) Seeing that you are calling the container a constructor here, probably means that you are not adhering to the principle that there should be only 3 calls to the container, 1 to register component, 1 to retrieve a top level component, and 1 to release the container.
I suggest you read a bit more about depedency injection and Ioc containers in general to fully understand how to work with this container.

NHibernate config properties in Fluent NHibernate

I am considering using Fluent NHibernate for my project and I haven't found any documentation on whether FH supports NHibernate settings such as show_sql and prepare_sql. I could live without show_sql in a pinch, but prepare_sql is important for ensuring good performance at run time.
Can anyone tell me if it's possible to configure these settings in Fluent NHibernate?
Yes, you can.
Fluently.Configure()
.Database(ConfigureDatabase())
.Mappings(ConfigureMapping)
.ExposeConfiguration(ModifyConfiguration)
.BuildConfiguration();
And now in ModifyConfiguration method you have plain NHibernate's Configuration object to modify
private void ModifyConfiguration(Configuration configuration)
{
// set parameters here like this:
configuration.Properties["show_sql"] = "true";
}
Some of the settings are exposed through the fluent API.
See here for examples: Database Configuration
Anything that isn't supported through specific fluent calls can be set by manipulating the native NHibernate.Cfg.Configuration object. Either way you can do everything in code that you can with the configuration file.

Weird override problem with Fluent NHibernate and .NET 4

I recently asked a question about using Fluent NHibernate with .NET 4 - I solved that problem, but met a new one.
Summary
My main problem (at the moment) is configuring the database. I'm following this guide, but trying to work against SQL Server 2008 Express instead, as that's what I'll be using and thus what I need to learn.
The failing code:
public static ISessionFactory CreateSessionFactory()
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("mssql")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>())
.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
.BuildSessionFactory();
}
When I try to run my application, I get the following exception on the last line (.BuildSessionFactory()):
Inheritance security rules violated while overriding member: 'FluentNHibernate.Cfg.FluentConfigurationException.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)'. Security accessibility of the overriding method must match the security accessibility of the method being overriden.
What is causing this?
From the Microsoft Connect issue:
Security attributes need to be
re-applied on types that derive from
other types that also have security
attributes.
Maybe FluentConfigurationException needs to apply a [SecurityPermission] attribute to its GetObjectData() method.
Else check out this blog post.
EDIT: The final solution was adding [SecurityCritical] to FluentConfigurationException.GetObjectData()