23

I am now doing a dynamic query in my project by using System.Linq.Dynamic. I use Autofac as my default IOC container. But Now I get a problem on registering generic components, here is my code :

the interface:

public interface IDynamicQuery
{
    IQueryable<T> CreateDynamicQuery<T>(string propertyName, string propertyValue, Expression<Func<T, bool>> where) where T:class;
}

the class:

public class DynamicQuery :IDynamicQuery
{
    public DynamicQuery(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
    }
    private  readonly IUnitOfWork unitOfWork;

    public IQueryable<T> CreateDynamicQuery<T>(string propertyName, string propertyValue, Expression<Func<T, bool>> where) where T:class
    {
        var appRepository = unitOfWork.Repository<T>();

        IQueryable<T> queryResult = null;
        if (propertyName.Contains('$'))  
            propertyName = propertyName.Replace('$', '.');
        queryResult = appRepository.GetMany(where).Where("" + propertyName + ".Contains(\"" + propertyValue + "\")");
        return queryResult;
    }
}

Then I register them in the application start entry:

builder.RegisterType<IDynamicQuery>().As<DynamicQuery>().InstancePerHttpRequest();

But When I start up my project based on MVC 4, it throws me an exception like :

 The type 'TinyFrame.Framework.Query.IDynamicQuery' is not assignable to service 'TinyFrame.Framework.Query.DynamicQuery'.

the Exception throws at : var container = builder.Build();

I know how to register a generic class in autofac, but I don't know how to register above class I raised, anyone can help me on this? I am a new comer to autofac, thx in advice.

superjos
  • 12,189
  • 6
  • 89
  • 134
CharlieShi
  • 888
  • 3
  • 17
  • 43
  • 3
    You have it the wrong way round. An `IDynamicQuery` is not a `DynamicQuery` but a `DynamicQuery` IS an `IDynamicQuery`. – Aron Apr 28 '14 at 01:24
  • @Aron Oh my god, how careless of me..... I had a bad sleep last night. thx for advice. – CharlieShi Apr 28 '14 at 01:32

6 Answers6

46

@CharlieShi I had the same problem and I noticed that I was forgetting to add inheritance to my class. But in your case, try this:

builder.RegisterType<DynamicQuery>().As<IDynamicQuery>().InstancePerHttpRequest();

reverse the interface with the class!

superjos
  • 12,189
  • 6
  • 89
  • 134
Alisom Martins
  • 688
  • 9
  • 16
13

In my case, I had reversed the order in which the interface and the classes are to be mentioned:

builder.RegisterType<CONCRETE_CLASS>().As<INTERFACE>();
Bugs
  • 4,491
  • 9
  • 32
  • 41
Sheena Agrawal
  • 700
  • 1
  • 7
  • 15
7

This can be done if you forget to add the Interface to your class.

builder.RegisterType<People>().As<IPeople>();

This will cause the error

public class People

This will resolve it

public class People : IPeople 
MyDaftQuestions
  • 4,487
  • 17
  • 63
  • 120
0

You can register the complete assembly with autofac container like this way:

 builder.RegisterAssemblyTypes(
            typeof(YourClass).Assembly)
            .AsImplementedInterfaces()
            .InstancePerLifetimeScope();

In your case, if you want to register the perticular type only, then just use the following:

builder.RegisterType<DynamicQuery>()
             .As<IDynamicQuery>()
             .InstancePerLifetimeScope();

You can set the lifetime according to your business requirements.

error_handler
  • 1,191
  • 11
  • 19
0

Your problem is that you try to map interface on implementation, just swap IDynamicQuery and DynamicQuery. And don't forget to make a rebuild.

It should be like:

builder.RegisterType<DynamicQuery>().As<IDynamicQuery>().InstancePerHttpRequest();
0

Encountered the same problem but the cause was different in my case. I didn't see that I was registering the same type twice. I find this error message is misleading.

Cristik
  • 30,989
  • 25
  • 91
  • 127
j.e.
  • 69
  • 3