.Net RIA Services: DomainService Needs a Parameterless Constructor?

℡╲_俬逩灬. 提交于 2019-12-04 23:45:18

问题


I'm using the July CTP of .Net RIA Services in an ASP.Net application with some Silverlight components. I'm calling the RIA Services from Silverlight.

My problem arose when I tried to use Unity and constructor dependency injection in my Domain Service (a LinqToEntitiesDomainService object). The Silverlight application now complains about not having a parameterless constructor.

I don't want to have a parameterless constructor, I want Unity to resolve the constructor arguments. Is this possible? Am I doing something wrong? Or should I find another way to inject my constructor arguments?

public class DashboardService : LinqToEntitiesDomainService<DashboardEntities>
{
    private IUserService userService;

    public DashboardService(IUserService userService)
        : base()
    {
        if (userService == null)
        {
            throw ExceptionBuilder.ArgumentNull("userService");
        }
        this.userService = userService;
    }

    ...

Here's the error I'm getting:

Webpage error details

User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Timestamp: Tue, 18 Aug 2009 14:34:54 UTC


Message: Unhandled Error in Silverlight 2 Application No parameterless constructor defined for this object.   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)
   at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Web.DomainServices.DomainService.DefaultDomainServiceFactory.CreateDomainService(Type domainServiceType, DomainServiceContext context)
   at System.Web.Ria.DataServiceFactory.GetDataService(HttpContext context)
   at System.Web.Ria.DataServiceFactory.System.Web.IHttpHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)
Line: 1
Char: 1
Code: 0
URI: http://dev.localhost/Home

回答1:


Since you have a DomainService with a parameter in its ctor, and more generally needs to be constructed through some sort of IoC container or dependency injection system, you'll need to provide an app-level domain service factory. Your factory is then responsible for instantiating the domain service (and disposing it), and it can do so by calling into another API, such as Unity in your case.

Here's a basic example:

In Global.asax.cs of your app, add the following:

public class Global : HttpApplication {

    static Global() {
        DomainService.Factory = new MyAppDomainServiceFactory();
    }
}

internal sealed class MyAppDomainServiceFactory : IDomainServiceFactory {

    public DomainService CreateDomainService(Type domainServiceType,
                                             DomainServiceContext context) {
        DomainService ds = ... // code to create a service, or look it up
                               // from a container

        if (ds != null) {
            ds.Initialize(context);
        }
        return ds;
    }

    public void ReleaseDomainService(DomainService domainService) {
        // any custom logic that must be run to dispose a domain service
        domainService.Dispose();
    }
}

Hope that helps!




回答2:


@Brien, I assume the 'IUserService' depends on IUnitOfWork, where the IUnitOfWork is the DashboardEntities ?

Like this UserRepository:

public class UserRepository : BaseRepository<User>, IUserRepository
{
    protected BaseRepository(IUnitOfWork unitOfWork)
    {
    }

    ...
}

And this IUnitOfWork:

public partial class DashboardEntities : ObjectContext, IUnitOfWork
{
    public const string ConnectionString = "name=DashboardEntities";
    public const string ContainerName = "DashboardEntities";

    public DashboardEntities()
        : base(ConnectionString, ContainerName)
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }

    ...
}

I'm using this design. One thing I noticed is that the DashboardEntities class is created more than once. The first time it's created by Unity (and will only be created once because it's declared as an Singleton in the Unity Configuration).

But the next time, it seems that a new DashboardEntities class is created during the initialize from the DomainService (DashboardService) ? This is no big deal because the DomainService will not use this ObjectContext, it will use the ObjectContext which is injected by Unity in the Repositories.

Can someone confirm this design or show some more light on this issue ?



来源:https://stackoverflow.com/questions/1294331/net-ria-services-domainservice-needs-a-parameterless-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!