2009-08-18 3 views
6

J'utilise le CTP de juillet des services .Net RIA dans une application ASP.Net avec des composants Silverlight. J'appelle les services RIA de Silverlight.Services .Net RIA: DomainService a besoin d'un constructeur sans paramètre?

Mon problème est survenu lorsque j'ai essayé d'utiliser l'injection de dépendance Unity et constructor dans mon service de domaine (un objet LinqToEntitiesDomainService). L'application Silverlight se plaint maintenant de ne pas avoir de constructeur sans paramètre.

Je ne veux pas avoir un constructeur sans paramètre, je veux que Unity résolve les arguments du constructeur. Est-ce possible? Est-ce que je fais quelque chose de mal? Ou devrais-je trouver un autre moyen d'injecter mes arguments constructeur?

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

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

    ... 

Voici l'erreur que je reçois:

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 

Répondre

12

Puisque vous avez un DomainService avec un paramètre dans son cteur, et plus généralement besoin d'être construit par une sorte de conteneur IoC ou l'injection de dépendance système, vous devez fournir une fabrique de services de domaine au niveau de l'application. Votre usine est alors responsable de l'instanciation du service de domaine (et de son élimination), et il peut le faire en appelant une autre API, telle que Unity dans votre cas.

Voici un exemple de base:

Dans Global.asax.cs de votre application, ajoutez ce qui suit:

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!

+0

Je le cherchais. Merci pour ça :) – Davita

0

@Brien, je suppose que le 'IUserService' dépend de IUnitOfWork, où IUnitOfWork est le DashboardEntities?

Vous aimez cette UserRepository:

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

    ... 
} 

Et ce 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; 
    } 

    ... 
} 

J'utilise cette conception. Une chose que j'ai remarquée est que la classe DashboardEntities est créée plus d'une fois. La première fois, elle est créée par Unity (et ne sera créée qu'une seule fois car elle est déclarée comme Singleton dans la configuration Unity).

Mais la prochaine fois, il semble qu'une nouvelle classe DashboardEntities est créée lors de l'initialisation à partir du DomainService (DashboardService)? Ce n'est pas un gros problème car DomainService n'utilisera pas ObjectContext, il utilisera ObjectContext qui est injecté par Unity dans les référentiels.

Quelqu'un peut-il confirmer ce design ou montrer plus de lumière sur ce problème?