Need help configuring Castle-Windsor - castle-windsor

I have these base interfaces and providers in one assembly (Assembly1):
public interface IEntity
{
}
public interface IDao
{
}
public interface IReadDao<T> : IDao
where T : IEntity
{
IEnumerable<T> GetAll();
}
public class NHibernate<T> : IReadDao<T>
where T : IEntity
{
public IEnumerable<T> GetAll()
{
return new List<T>();
}
}
And I have this implementation inside another assembly (Assembly2):
public class Product : IEntity
{
public string Code { get; set; }
}
public interface IProductDao : IReadDao<Product>
{
IEnumerable<Product> GetByCode(string code);
}
public class ProductDao : NHibernate<Product>, IProductDao
{
public IEnumerable<Product> GetByCode(string code)
{
return new List<Product>();
}
}
I want to be able to get IRead<Product> and IProductDao from the container.
I am using this registration:
container.Register(
AllTypes.FromAssemblyNamed("Assembly2")
.BasedOn(typeof(IReadDao<>)).WithService.FromInterface(),
AllTypes.FromAssemblyNamed("Assembly1")
.BasedOn(typeof(IReadDao<>)).WithService.Base());
The IReadDao<Product> works great. The container gives me ProductDao. But if I try to get IProductDao, the container throws ComponentNotFoundException. How can I correctly configure the registration?

Try changing your Assembly2 registration to use all interfaces:
AllTypes.FromAssemblyNamed("Assembly2").BasedOn(typeof(IReadDao<>))
.WithService.Select((t, baseType) => t.GetInterfaces());

Related

How to register generic UnitOfWork<TContext> with non generic IUnitOfWork in 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());

mvvmcross Init method is not called if I inherit froma base ViewModel which is derived from MvxViewModel

First I'm using mvvmcross version 3.0.13. When a class is inherited from a base class, which is inherited from MvxViewModel, the Init method won't be called from IoC. Current ugly workaround is to call the Init in the constructor. Could this be a bug or is there another pattern to use?
In both classes (base and child of that base) it won't be called. For example:
public class BaseViewModel : MvxViewModel
{
protected CDataImportService DataImportService { get; private set; }
protected CSettingService SettingService { get; private set; }
protected CDataService DataService { get; private set; }
protected CDocumentService DocumentService { get; private set; }
public BaseViewModel(IDataService objDataService, IDataImportService objDataImportService, IDocumentService objDocumentService, ISettingService objSettingService)
{
DataImportService = (CDataImportService)objDataImportService;
SettingService = (CSettingService)objSettingService;
DataService = (CDataService)objDataService;
DocumentService = (CDocumentService) objDocumentService;
}
public void Init()
{
Mvx.Trace("Init called in {0}", GetType().Name);
}
}
public class DocumentsViewModel : BaseViewModel
{
public MenuViewModel(IDataService objDataService, IDataImportService objDataImportService, IDocumentService objDocumentService, ISettingService objSettingService)
: base(objDataService, objDataImportService, objDocumentService, objSettingService)
{
}
}
IOC on it's own does not call the Constructor-Init-Reload-Start sequence.
IOC is a general C# service, and only calls the constructor part.
If you want the entire sequence called then you can access this via the IMvxViewModelLoader object - e.g Mvx.Resolve<IMvxViewModelLoader>().LoadViewModel(MvxViewModelRequest<MyViewModel>.GetDefaultRequest(), null);
By default, this will use the Default ViewModel Locator to create a view model instance - https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross/ViewModels/MvxDefaultViewModelLocator.cs
If it helps, for some more information:
mvvmcross IOC is described fully in https://github.com/MvvmCross/MvvmCross/wiki/Service-Location-and-Inversion-of-Control
view model location is briefly discussed in https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup

PowerMock expectNew how to specify the type of the parameters

When I use PowerMock to mock the constructor,I want to specify the type of the paremeters. I use the method
PowerMock.expectNew(Class<T> type, Class<?>[] parameterTypes, Object... arguments)
If I want to specify the String type, what shoud I fill in the parameterTypes?
Given these example classes:
public class MyClass {
public MyClass(String theParam) {
//Some interesting code...
}
}
public class MyFactory {
public MyClass createMyClass() {
return new MyClass("foo");
}
}
Then you would do an expectNew as follows:
public class MyFactoryTest {
#Test
public void testCreateMyClass() {
//...
PowerMock.expectNew(MyClass.class, new Class[] {String.class}, "foo");
//...
}
}

Generic return types with interface type params in WCF

How can I return interface types in generic type parameters from the OperationContracts in my WCF REST service? More specifically, it works for one operation but not when I add a second operation with a generic T that is an interface.
I'm using JSON as the request and response format, feeding a non-WCF client that parses the JSON responses for the data it needs. I am not using SOAP, or the WSDL generated by the service.
My service interface:
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(ServiceKnownTypesHelper))]
public interface IMyService
{
[WebGet(UriTemplate="count")]
[OperationContract]
IServiceResult<int> GetCount();
[WebGet(UriTemplate="desc")]
[OperationContract]
IServiceResult<string> GetDescription();
[WebGet(UriTemplate="foo")]
[OperationContract]
IServiceResult<IFooData> GetFooData();
// Fails when I invoke either method if I uncomment this operation.
//[WebGet(UriTemplate="bar")]
//[OperationContract]
//IServiceResult<IBarData> GetBarData();
}
I left GetCount() and GetDescription() in the example to point out that those two generic results work fine, but obviously they are concrete types. And even GetFooData() works fine until I add a second method of IServiceResult<T> where T is an interface.
The return types of GetFooData() and GetBarData() are not the same, nor are the concrete classes that implement them.
You may imagine that I've reduced the implementation to a skeleton as I don't think the implementation is the heart of the problem:
#region My service implementation
public class MyService : IMyService
{
public IServiceResult<int> GetCount()
{
return new ServiceResult<int>(42);
}
public IServiceResult<string> GetDescription()
{
return new ServiceResult<string>("Muffins");
}
public IServiceResult<IFooData> GetFooData()
{
return new ServiceResult<IFooData>(new FooData() { Foo = 99 });
}
public IServiceResult<IBarData> GetBarData()
{
return new ServiceResult<IBarData>(new BarData() { Bar = "Elvis was here" });
}
}
#endregion
#region ServiceKnownTypesHelper.GetServiceKnownTypes():
public static class ServiceKnownTypesHelper
{
private static IList<Type> serviceKnownTypes = new List<Type>()
{
typeof(FooData),
typeof(BarData),
typeof(ServiceResult<int>),
typeof(ServiceResult<string>),
typeof(ServiceResult<IFooData>),
typeof(ServiceResult<IBarData>),
};
public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider paramIgnored)
{
return serviceKnownTypes;
}
}
#endregion
#region IServiceResult<T> and its concrete implementation:
public interface IServiceResult<T>
{
IList<string> Errors { get; }
T Value { get; set; }
}
[DataContract]
public class ServiceResult<T> : IServiceResult<T>
{
public ServiceResult(T value)
{
this.Value = value;
}
private IList<string> errors = new List<string>();
[DataMember]
public IList<string> Errors
{
get
{
return this.errors;
}
}
[DataMember]
public T Value { get; set; }
}
#endregion
#region IFooData and its concrete implementation:
public interface IFooData
{
int Foo { get; set; }
}
[DataContract]
public class FooData: IFooData
{
[DataMember]
public int Foo { get; set; }
}
#endregion
#region IBarData and its concrete implementation:
public interface IBarData
{
string Bar { get; set; }
}
[DataContract]
public class BarData: IBarData
{
[DataMember]
public string Bar { get; set; }
}
#endregion
And the error message when I invoke GetBarData() from the browser:
Type 'ServiceResult`1[IBarData]' cannot be added to list of known types since
another type 'ServiceResult`1[IFooData]' with the same data contract name
'http://schemas.datacontract.org/2004/07/ServiceResultOfanyType' is
already present.
The rest of the error message is a red herring about colliding collection types List<Test> and Test[], which isn't the case here.
Clearly, IFooData and IBarData aren't the same, nor are the classes that implement them.
So why do ServiceResult<IFooData> and ServiceResult<IBarData> both resolve to ServiceResultOfanyType?
Am I missing something, or is there no way to fix this?
After much trial and error, I've finally got this working with minimal changes:
My service operations now return ServiceResult<T> instead of IServiceResult<T>. In fact, IServiceResult<T> is now gone entirely.
GetServiceKnownTypes() no longer returns all the variants of ServiceResult<T>. I only return the DataContracts used as T.
#region My service interface
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(ServiceKnownTypesHelper))]
public interface IMyService
{
[WebGet(UriTemplate="count")]
[OperationContract]
ServiceResult<int> GetCount();
[WebGet(UriTemplate="desc")]
[OperationContract]
ServiceResult<string> GetDescription();
[WebGet(UriTemplate="foo")]
[OperationContract]
ServiceResult<IFooData> GetFooData();
[WebGet(UriTemplate="bar")]
[OperationContract]
ServiceResult<IBarData> GetBarData();
}
#endregion
#region My service implementation (minus bodies)
public class MyService : IMyService
{
public ServiceResult<int> GetCount() {}
public ServiceResult<string> GetDescription() {}
public ServiceResult<IFooData> GetFooData() {}
public ServiceResult<IBarData> GetBarData() {}
}
#endregion
#region ServiceKnownTypes
// My list of ServiceKnownTypes is now much shorter and simpler. I was feeding the service too much information
public static class ServiceKnownTypesHelper
{
private static IList<Type> serviceKnownTypes = new List<Type>()
{
typeof(FooData),
typeof(BarData),
//typeof(ServiceResult<int>),
//typeof(ServiceResult<string>),
//typeof(ServiceResult<IFooData>),
//typeof(ServiceResult<IBarData>),
};
// Remaining implementation is the same as before
}
#endregion
#region ServiceResult<T> with no interface (it's not used or needed)
[DataContract]
public class ServiceResult<T> //: IServiceResult<T>
{
// implementation is the same as before
}
#endregion
I can now invoke all of those methods and get back lists of generic types referred to by their interfaces in the ServiceContract.

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.