How to register generic UnitOfWork<TContext> with non generic IUnitOfWork in Castle Windsor? - castle-windsor

This is my code:
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private readonly Dictionary<Type, object> _repositories;
private bool _disposed;
...................
EmployeeService.cs
public class EmployeeService : EntityService<Employee>, IEmployeeService
{
readonly IUnitOfWork _unitOfWork;
readonly IRepository<Employee> _repository;
........
in console app when I call:
var employeeService = Injector.Instance.Resolve<IEmployeeService>();
I am getting below error message:
An unhandled exception of type 'Castle.MicroKernel.Handlers.GenericHandlerTypeMismatchException' occurred in Castle.Windsor.dll
Additional information: Types EfContext.DAL.IDbContext don't satisfy generic constraints of implementation type EfContext.DAL.UnitOfWork1 of component 'EfContext.DAL.UnitOfWork1'.this is likely a bug in the IGenericImplementationMatchingStrategy used (EfContext.DependencyInjection.UseStringGenericStrategy)
public class ConsoleAppInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Component.For(typeof(IUnitOfWork)).ImplementedBy(typeof(UnitOfWork<>), new UseStringGenericStrategy()).LifestyleTransient());
}
}
public class UseStringGenericStrategy : IGenericImplementationMatchingStrategy
{
public Type[] GetGenericArguments(ComponentModel model, CreationContext context)
{
if (context.RequestedType == typeof(IUnitOfWork))
{
var res = new[] { typeof(object) };
return res;
}
return null;
}
}

I have fixed my issue with changing the register line to:
// register
container.Register(Component.For(typeof(IUnitOfWork)).ImplementedBy(typeof(UnitOfWork<MyDbContext>),
new UseTypeGenericStrategy()).LifestyleTransient());

Related

"You should only initialize MvxBindingSingletonCache once" error when have several test classes

I run into a strange exception. In my test project, I use Moq, xUnit, and MvvmCross.Tests.
When I run my tests from one class - everything works just fine. When I run tests from 2 classes I get MvvmCross.Exceptions.MvxException.
I have 2 identical (initialization is identical) classes VitalsDataTests and GetReimbursedTests:
public class VitalsDataTests : MvxIoCSupportingTest
{
public VitalsDataTests()
{
base.Setup();
}
protected MockDispatcher MockDispatcher
{
get;
private set;
}
protected override void AdditionalSetup()
{
MockDispatcher = new MockDispatcher();
Ioc.RegisterSingleton<IMvxViewDispatcher>(MockDispatcher);
Ioc.RegisterSingleton<IMvxMainThreadDispatcher>(MockDispatcher);
Ioc.RegisterSingleton<IMvxMainThreadAsyncDispatcher>(MockDispatcher);
}
...
}
Here is my MockDispatcher:
public class MockDispatcher
: MvxMainThreadDispatcher
, IMvxViewDispatcher
{
public readonly List<MvxViewModelRequest> Requests;
public readonly List<MvxPresentationHint> Hints;
public MockDispatcher()
{
if (Hints == null) Hints = new List<MvxPresentationHint>();
if (Requests == null) Requests = new List<MvxViewModelRequest>();
}
public override bool IsOnMainThread { get; }
public Task<bool> ChangePresentation(MvxPresentationHint hint)
{
Hints.Add(hint);
return Task.FromResult(true);
}
public async Task ExecuteOnMainThreadAsync(Action action, bool maskExceptions = true)
{
await Task.Run(action);
}
public async Task ExecuteOnMainThreadAsync(Func<Task> action, bool maskExceptions = true)
{
await Task.Run(action);
}
public override bool RequestMainThreadAction(Action action, bool maskExceptions = true)
{
action();
return true;
}
public Task<bool> ShowViewModel(MvxViewModelRequest request)
{
Requests.Add(request);
return Task.FromResult(true);
}
}
What I tried:
Clearing MvxSingleton and MvxBindingSingletonCache singletons in the constructor of each class before I call base.Setup():
MvxSingleton.ClearAllSingletons();
MvxBindingSingletonCache.ClearAllSingletons();
Not sure what I'm doing wrong.
thank you for your help.
I was able to solve this error by adding XUnit Collection Attribute for each test class, like this:
[Collection("ViewModels")]
public class GetReimbursedTests : BaseTest
{
...
}

Castle.MicroKernel.ComponentNotFoundException with TypedFactoryFacility

I am having some problem resolving ITcpServer when using TypedFactoryFacility. It seems that Windsor does not find a suitable component to be returned from factory for the interface. What is specific to my case is that the interface ITcpServer is non-generic while classes implementing it are both generic.
The following code throws when run:
Unhandled Exception: Castle.MicroKernel.ComponentNotFoundException: No
component for supporting the service
ConsoleApplication1.StandardTcpServer`1 was found at
Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type
service, IDictionary arguments, IReleasePolicy policy) at
Castle.Facilities.TypedFactory.TypedFactoryComponentResolver.Resolve(IKernelInternal
kernel, IReleasePolicy scope) at
Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Resolve(IInvocation
invocation) at
Castle.Facilities.TypedFactory.Internal.TypedFactoryInterceptor.Intercept(IInvocation
invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ITcpServerFactoryProxy.Create[T](String serverType,
T something)
The code:
class Program
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.Install(new MyWindsorInstaller());
var f = container.Resolve<ITcpServerFactory>();
var tcpServer = f.Create("standard", "something");
tcpServer.Start();
}
}
public class MyWindsorInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<ITcpServer>().ImplementedBy(typeof(LibUvTcpServer<>)),
Component.For<ITcpServer>().ImplementedBy(typeof(StandardTcpServer<>)),
Component.For<ITcpServerFactory>().AsFactory(c => c.SelectedWith(new TcpServerComponentSelector()))
);
}
}
public class TcpServerComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments)
{
var serverType = (string)arguments.First();
return serverType == "standard" ? typeof (StandardTcpServer<>) : typeof(LibUvTcpServer<>);
}
}
public interface ITcpServerFactory
{
ITcpServer Create<T>(string serverType, T something);
}
public class StandardTcpServer<T> : ITcpServer
{
public void Start()
{
Console.WriteLine("Started...");
}
}
public class LibUvTcpServer<T> : ITcpServer
{
private readonly T something;
public LibUvTcpServer(T something)
{
this.something = something;
}
public void Start()
{
Console.WriteLine("Started...");
}
}
public interface ITcpServer
{
void Start();
}
Any help in solving the problem would be appreciated.
Change the following:
protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments)
{
var serverType = (string)arguments.First();
if (serverType == "standard")
{
return typeof(StandardTcpServer<>).MakeGenericType(arguments[1].GetType());
}
else
{
return typeof(LibUvTcpServer<>).MakeGenericType(arguments[1].GetType());
}
}
and the registration:
Component.For<ITcpServer>().Forward(typeof(LibUvTcpServer<>)).ImplementedBy(typeof(LibUvTcpServer<>)),
Component.For<ITcpServer>().Forward(typeof(StandardTcpServer<>)).ImplementedBy(typeof(StandardTcpServer<>)),
or if you only need to resolve through the factory:
Component.For(typeof(LibUvTcpServer<>)),
Component.For(typeof(StandardTcpServer<>)),
Good luck,
Marwijn.

Castle Scoped Lifestyle not working

Trying to find the real cause of this and not having much fun!
Type is not resolved for member 'Castle.MicroKernel.Lifestyle.Scoped.CallContextLifetimeScope+SerializationReference,Castle.Windsor, Version=3.1.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc'.
This looks like a bug considering I have nothing register with the container using this lifestyle.
Faced same issue while doing MSTest. Adding Castle.Windsor.dll to GAC worked for me.
gacutil.exe /if "C:\Castle.Windsor.3.1.0\lib\net40\Castle.Windsor.dll"
I'm not sure what you are trying to do, but if your goal is implementing an IDependencyResolver (which looks like it since you are using scopes):
If you are implementing an IDependencyResolver, don't try to be clever and inherit from your IDependencyScope implementation. Create the Resolver from scratch. This is how I implemented my dependency resolver (which works):
public class WindsorDependencyResolver : IDependencyResolver {
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public object GetService(Type serviceType)
{
return _container.Kernel.HasComponent(serviceType)
? _container.Resolve(serviceType)
: null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
}
}
public class WindsorDependencyScope : IDependencyScope {
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
private bool _disposed;
public WindsorDependencyScope(IWindsorContainer container)
{
_container = container;
_scope = _container.BeginScope();
}
public object GetService(Type serviceType)
{
EnsureNotDisposed();
return _container.Kernel.HasComponent(serviceType)
? _container.Kernel.Resolve(serviceType)
: null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
EnsureNotDisposed();
return _container.ResolveAll(serviceType).Cast<object>();
}
public void Dispose()
{
if(_disposed) return;
_scope.Dispose();
_disposed = true;
GC.SuppressFinalize(this);
}
private void EnsureNotDisposed()
{
if(_disposed) throw new ObjectDisposedException("WindsorDependencyScope");
}
}
And this was my first attempt (which produced your error):
public class WindsorDependencyResolver : WindsorDependencyScope, IDependencyResolver {
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
: base(container)
{
_container = container;
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
}

Dependency Issues In AutoMapper Type Convertors

I've encountered a problem using AutoMapper and Windsor. I've created a custom type convertor that depends on another object, which can be resolved from the container but when I attempt to use the convertor in a mapping process, an AutoMapper.AutoMapperMappingException is thrown, stating that my Type Convertor does not have a default constructor.
I've recreated the issue in the proof of concept code below:
using System;
using System.Reflection;
using AutoMapper;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using NUnit.Framework;
public class ObjectOne
{
public string Name { get; set; }
public string Description { get; set; }
}
public class ObjectTwo
{
public string ObjName { get; set; }
public string ObjDescr { get; set; }
}
public interface ILoggingService
{
void Log(string message);
}
public class ConsoleLogger : ILoggingService
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
public class MyObjectConvertor : ITypeConverter<ObjectOne, ObjectTwo>
{
private readonly ILoggingService _loggingService;
public MyObjectConvertor(ILoggingService loggingService)
{
if (loggingService == null) throw new ArgumentNullException("loggingService");
_loggingService = loggingService;
}
public ObjectTwo Convert(ResolutionContext context)
{
_loggingService.Log(MethodBase.GetCurrentMethod().ToString());
var source = (ObjectOne)context.SourceValue;
return new ObjectTwo { ObjName = source.Name, ObjDescr = source.Description };
}
public void LogIt(string message)
{
_loggingService.Log(message);
}
}
public class MappingContractsWindsorInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ILoggingService>().ImplementedBy<ConsoleLogger>(),
Component.For<MyObjectConvertor>());
}
}
[TestFixture]
public class MappingTester
{
private IWindsorContainer container;
[TestFixtureSetUp]
public void SetupFixture()
{
container = new WindsorContainer();
container.Install(new MappingContractsWindsorInstaller());
Mapper.CreateMap<ObjectOne, ObjectTwo>().ConvertUsing<MyObjectConvertor>();
Mapper.Configuration.ConstructServicesUsing(container.Resolve);
Mapper.AssertConfigurationIsValid();
}
[Test]
public void MyObjectConvertorReturnedWithLoggerInjectedOk()
{ // Proof that the Convertor is returned from the
// container with the dependency fulfilled
var conv = container.Resolve<MyObjectConvertor>();
conv.LogIt("Hello World");
}
[Test]
public void ObjectOneMapsToTwo()
{
var source = new ObjectOne()
{
Name = "Foo",
Description = "Bar"
};
var result = Mapper.Map<ObjectOne, ObjectTwo>(source);
Assert.That(result.ObjName == source.Name);
Assert.That(result.ObjDescr == source.Description);
}
}
When the tests are ran, the following exception is thrown during ObjectOneMapsToTwo():
Test 'MappingTester.ObjectOneMapsToTwo' failed: AutoMapper.AutoMapperMappingException : Trying to map ObjectOne to ObjectTwo.
Using mapping configuration for ObjectOne to ObjectTwo
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
----> System.ArgumentException : Type 'MyObjectConvertor' does not have a default constructor
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
at AutoMapper.MappingEngine.Map(Object source, Type sourceType, Type destinationType, Action`1 opts)
at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source)
at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
Class1.cs(99,0): at MappingTester.ObjectOneMapsToTwo()
--ArgumentException
at System.Linq.Expressions.Expression.New(Type type)
at AutoMapper.DelegateFactory.<>c__DisplayClass1.<CreateCtor>b__0(Type t)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at AutoMapper.DelegateFactory.CreateCtor(Type type)
at AutoMapper.Mappers.ObjectCreator.CreateObject(Type type)
at AutoMapper.MappingExpression`2.<ConvertUsing>b__1a[TTypeConverter]()
at AutoMapper.DeferredInstantiatedConverter`2.Convert(ResolutionContext context)
at AutoMapper.MappingExpression`2.<>c__DisplayClass15.<ConvertUsing>b__14(ResolutionContext context)
at AutoMapper.Mappers.TypeMapObjectMapperRegistry.CustomMapperStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
This project is referencing the following:
<packages>
<package id="NUnit" version="2.5.10.11092" />
<package id="Castle.Core" version="2.5.2" />
<package id="Castle.Windsor" version="2.5.3" />
<package id="AutoMapper" version="2.0.0" />
</packages>
The test MyObjectConvertorReturnedWithLoggerInjectedOk() passes, proving that the typeconvertor is being returned from the container with the dependency passed in OK. But when Automapper tries to use the convertor, it throws the exception.
Any help on this would be appreciated.
Thanks in advance.
This is actually a bug in AutoMapper, fixed after the 2.0 release and will be out in the upcoming 2.1 release. You can pull down the nightlies to get the latest stable drop from AutoMapper.org

Castle Windsor, hook continer release in order to call explicit components release

I run this at the application Start Up
public class ConfigurationFacility : AbstractFacility {
private readonly List<string> configuredComponents = new List<string>();
protected override void Init() {
Kernel.ComponentRegistered += OnComponentRegistered;
// add environment configurators
}
private void OnComponentRegistered(string key, IHandler handler) {
// if the component is a configurator then run conf settings and add it to configuredComponents
}}
Question: How to hook tear down and to call explicit release for each ?
Thanks
You can use either the ComponentDestroyed event of IKernel or just implement IDisposable in your components. Here's a little sample code:
namespace WindsorInitConfig {
[TestFixture]
public class ConfigurationFacilityTests {
[Test]
public void tt() {
OneDisposableComponent component = null;
using (var container = new WindsorContainer()) {
container.AddFacility<ConfigurationFacility>();
container.AddComponent<OneDisposableComponent>();
component = container.Resolve<OneDisposableComponent>();
}
Assert.IsTrue(component.Disposed);
Assert.Contains(component, ConfigurationFacility.DestroyedComponents);
}
public class OneDisposableComponent : IDisposable {
public bool Disposed { get; private set; }
public void Dispose() {
Disposed = true;
}
}
public class ConfigurationFacility : AbstractFacility {
private readonly List<string> configuredComponents = new List<string>();
public static readonly ArrayList DestroyedComponents = new ArrayList();
protected override void Init() {
Kernel.ComponentRegistered += OnComponentRegistered;
Kernel.ComponentDestroyed += Kernel_ComponentDestroyed;
// add environment configurators
}
private void Kernel_ComponentDestroyed(ComponentModel model, object instance) {
DestroyedComponents.Add(instance);
// uninitialization, cleanup
}
private void OnComponentRegistered(string key, IHandler handler) {
// if the component is a configurator then run conf settings and add it to configuredComponents
configuredComponents.Add(key);}
}
}
}
The static ArrayList is only for demo purposes, of course.