2017-04-06 1 views
2

Je suis en train d'utiliser ninject avec l'identité asp.net et actuellement je faisais ce qui suit pour les liaisons:Ninject avec l'identité asp.net

kernel.Bind(typeof(IUserStore<>)).To(typeof(UserStore<>)); 

Ici vous avez des classes: définitions

public interface IUser : IUser<string> 

public interface IUserStore<TUser> : IUserStore<TUser, string>, IDisposable where TUser : class, IUser<string> 

public class IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>, IGenerateKeys 

public class UserStore<TUser> : UserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUserStore<TUser>, IUserStore<TUser, string> where TUser : IdentityUser, new() 

public class Context { 
    public Context(ILogger Logger, Dictionary<string, string> LocalConfig, IUserStore<IUser> UserManager 
     ){...} 
} 

Lorsque j'essaie de faire kernel.Get<Context>() je reçois l'erreur de ne pas être en mesure de lancer IUserStore à UserStore.

Unable to cast object of type 'UserStore`1[IdentityUser]' to type 'Microsoft.AspNet.Identity.IUserStore`1[Microsoft.AspNet.Identity.IUser]'. 

Je ne comprends pas vraiment pourquoi cela ne fonctionne pas, mais en fait essayer la IUserStore<IdentityUser> dummy = new Store<IdentityUser>() suivante donne aucune erreur de compilation, mais ce IUserStore<IUser> dummy = new Store<IdentityUser>() fait, mais je ne peux pas understande pourquoi depuis IdentityUser implémente IUser.

Quelqu'un at-il eu un problème similaire?

+1

Vous confondez le paramètre générique avec le type lui-même. Lorsque vous modifiez le paramètre de type d'un objet générique, vous modifiez son type réel. Donc, un 'IUserStore ' n'est pas la même chose qu'un 'IUserStore ', et vous ne pouvez pas affecter l'un à l'autre. Imaginez essayer d'assigner une 'Liste ' à une 'Liste '. cela n'a pas d'importance si les types génériques sont des implémentations les uns des autres. Maintenant, vous pouvez ajouter un objet IdentityUser à un objet IUserStore , mais ce n'est pas la même chose que d'essayer d'affecter le UserStore réel d'un autre type. –

+1

Je devrais clarifier un peu plus. Bien que ce que j'ai dit ci-dessus soit vrai, il y a des façons dans les langages basés sur .NET 4 (C# et VB) de le faire, mais cela nécessite que les interfaces soient spécifiées pour le faire. C'est ce qu'on appelle Covariance (ou Contravariance pour la façon inverse de le faire). Les interfaces IUser et IUserStore n'implémentent pas cela, donc le point reste. Vous pouvez lire plus sur la variance ici: https://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx –

Répondre

1

Si vous regardez Microsoft.AspNet.Identity.EntityFramework vous pouvez voir TUser dans UserStore doit être le type de IdentityUser et non IUser, c'est la raison pour laquelle vous avez obtenu erreur de compilation.

public namespace Microsoft.AspNet.Identity.EntityFramework 
{ 
// 
// Summary: 
//  EntityFramework based user store implementation that supports IUserStore, IUserLoginStore, 
//  IUserClaimStore and IUserRoleStore 
// 
// Type parameters: 
// TUser: 
public class UserStore<TUser> : UserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUserStore<TUser>, IUserStore<TUser, string>, IDisposable where TUser : IdentityUser 
{ 
    // 
    // Summary: 
    //  Default constuctor which uses a new instance of a default EntityyDbContext 
    public UserStore(); 
    // 
    // Summary: 
    //  Constructor 
    // 
    // Parameters: 
    // context: 
    public UserStore(DbContext context); 
    } 
} 

Vous devez toujours utiliser IdentityUser, car IUser est une interface minimale pour IdentityUser.

Si vous souhaitez utiliser Ninject avec l'identité, ce serait un peu difficile lite, vous pouvez trouver l'étape par étape solution ici: How to inject User Manager to Account Controller with default Identity Model in Identity 2 using Ninject