簡體   English   中英

Ninject WCF自托管注入

[英]Ninject WCF self hosted injection

我建立了一個自托管的WCF服務,該服務消耗了包含我所有存儲庫的工作單元。 存儲庫使用代碼優先EF連接到數據庫。 我正在使用Ninject.Extensions.Wcf.SelfHost包來啟動服務並使注入工作。

一切正常,直到我想將某些東西提交到數據庫。 我可以從數據庫中讀取記錄,但是無法正常工作。 在進行挖掘和調試后,我發現工作單元和存儲庫之間沒有共享我的數據庫上下文。 因此,當我在工作單元中提交內容時,上下文沒有要提交的更改。

有什么建議嗎?

這里的代碼:

服務的啟動代碼

    private static void StartNinjectSelfHosted(string address)
    {


        var service =
            NinjectWcfConfiguration.Create<SecurityService, NinjectServiceSelfHostFactory>(
                serviceHost =>
                serviceHost.AddServiceEndpoint(typeof(ISecurityService), new BasicHttpBinding(), address));

        selfHosted = new NinjectSelfHostBootstrapper(CreateKernel, service);
        selfHosted.Start();

        serviceAddress = address;

    }

    private static StandardKernel CreateKernel()
    {
        var kernel = new StandardKernel();

        ConfigurationAction scope = bind => bind.InRequestScope();

        kernel.Load((new NinjectModule[]
                        {
                            new ContextBinder(scope),
                            new ServiceBinder(scope) ,
                            new UnitOfWorkBinder(scope), 
                            new RepositoryBinder(scope),
                        }));

        return kernel;
    }

粘合劑

public class ContextBinder : NinjectModule
{
    private readonly ConfigurationAction _bindInScope;

    public ContextBinder(ConfigurationAction bindInScope)
    {
        _bindInScope = bindInScope;
    }

    public override void Load()
    {
        Kernel.Bind(typeof(SecurityContext)).ToSelf().InSingletonScope();
    }
}

public class ServiceBinder : NinjectModule
{

    private readonly ConfigurationAction _configurationAction;

    public ServiceBinder(ConfigurationAction configurationAction)
    {
        _configurationAction = configurationAction;
    }

    public override void Load()
    {
        Kernel.Bind(
            x => x.FromAssembliesMatching("WcfInterfaces*")
                     .SelectAllInterfaces()
                     .Join.FromAssembliesMatching("*Facade*")
                     .SelectAllClasses()
                     .BindDefaultInterface()
                     .Configure(_configurationAction));
    }
}

public class UnitOfWorkBinder : NinjectModule
{
    private readonly ConfigurationAction _configurationAction;

    public UnitOfWorkBinder(ConfigurationAction configurationAction)
    {
        _configurationAction = configurationAction;
    }

    public override void Load()
    {           

        Kernel.Bind(x => x
            /** Select all unit of work interfaces */
                             .FromAssembliesMatching("SecurityDomain*")
                             .SelectAllUnitOfWorkInterfaces()

                             /** Select all unit of work implementations */
                             .Join.FromAssembliesMatching("SecurityImplementation*")
                             .SelectAllUnitOfWorkImplementations()


                             /** Bind interfaces to implementations */
                             .BindDefaultInterface()

                             /** Configure the scope */
                             .Configure(_configurationAction));
    }
}

public class RepositoryBinder : NinjectModule
{

    private readonly ConfigurationAction _configurationAction;

    public RepositoryBinder(ConfigurationAction configurationAction)
    {
        _configurationAction = configurationAction;
    }


    public override void Load()
    {
        Kernel.Bind(x => x
            /** Select all default repository interfaces */
                              .FromAssembliesMatching("SecurityDomain*")
                              .SelectAllRepositoryInterfaces()

                              /** Select all repository implementations */
                              .Join.FromAssembliesMatching("SecurityImplementation*")
                              .SelectAllRepositoryImplementations()

                              /** Bind interfaces to implementations */
                              .BindDefaultInterface()

                              /** Configure the scope */
                              .Configure(_configurationAction));
    }
}

工作單位

public class UnitOfWork : IUnitOfWork
{
    private readonly SecurityContext _context;

    public UnitOfWork(SecurityContext context, ISecurityUnitOfWork security)
    {
        Console.WriteLine("*** Unit Of Work ContextHash: {0}***", context.Hash);

        _context = context;
        Security = security;
    }

    public void Commit(int userId)
    {
        Console.WriteLine("Context hash {0}", _context.Hash);

        using (var transaction = _context.Database.BeginTransaction())
        {
            try
            {

                DateTime now = DateTime.Now;
                foreach (var entry in _context.ChangeTracker.Entries<Entity>())
                {
                    switch (entry.State)
                    {
                        case EntityState.Added:
                            entry.Entity.CreationDate = now;
                            entry.Entity.CreationUserId = userId;
                            break;
                        case EntityState.Modified:
                            entry.Entity.ModificationDate = now;
                            entry.Entity.ModificationUserId = userId;
                            break;
                        case EntityState.Deleted:
                            entry.State = EntityState.Modified;
                            entry.Entity.Deleted = true;
                            break;
                    }
                }
                _context.SaveChanges();
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw;
            }
        }
    }

    public ISecurityUnitOfWork Security { get; private set; }
}

安全工作單位

public class SecurityUnitOfWork : ISecurityUnitOfWork
{
    public SecurityUnitOfWork(IAccountRepository accounts, IRoleRepository roles, IRightRepository rights, IUserRepository users, IApplicationRepository applications)
    {
        Applications = applications;
        Users = users;
        Rights = rights;
        Roles = roles;
        Accounts = accounts;
    }

    public IAccountRepository Accounts { get; private set; }

    public IRoleRepository Roles { get; private set; }

    public IRightRepository Rights { get; private set; }

    public IUserRepository Users { get; private set; }

    public IApplicationRepository Applications { get; private set; }
}

public class AccountRepository : GenericRepository<SecurityContext, Account>, IAccountRepository
{
    public AccountRepository(SecurityContext context)
        : base(context)
    {

    }
}

public class GenericRepository<TContext, TEntity> : IGenericRepository<TEntity>
    where TContext : DbContext
    where TEntity : class, IDeletable, IIdentifiable
{
    private readonly TContext _context;
    private readonly DbSet<TEntity> _entitySet;
    private IQueryable<TEntity> _entities;

    public GenericRepository(TContext context)
    {
        _context = context;
        _entitySet = context.Set<TEntity>();
        _entities = _entitySet;
    }

    /// <summary>
    ///     Gets the DbContext
    /// </summary>
    protected virtual TContext Context
    {
        get { return _context; }
    }

    /// <summary>
    ///     Gets the entities
    /// </summary>
    protected virtual IQueryable<TEntity> Entities
    {
        get { return _entities; }
        set { _entities = value; }
    }

    /// <summary>
    ///     Gets the editable dbset
    /// </summary>
    public virtual IDbSet<TEntity> EntitySet
    {
        get { return _entitySet; }
    }

    /// <summary>
    ///     Gets the entities
    /// </summary>
    protected virtual IQueryable<TEntity> Process(IEntityFilter<TEntity> filter = null, IEntitySorter<TEntity> sorter = null, IEntityIncluder<TEntity> includer = null)
    {
        var entities = _entities.Where(x => !x.Deleted);
        if (includer != null)
            entities = includer.AddInclusions(entities);

        if (filter != null)
            entities = filter.Filter(entities);
        if (sorter != null)
            entities = sorter.Sort(entities);
        return entities;
    }

    public virtual IQueryable<TEntity> List(IEntitySorter<TEntity> sorter = null, IEntityFilter<TEntity> filter = null, int? page = null, int? pageSize = null, IEntityIncluder<TEntity> includer = null)
    {
        if ((page.HasValue || pageSize.HasValue) && sorter == null)
        {
            throw new ArgumentException("You have to define a sorting order if you specify a page or pageSize! (IEntitySorter was null)");
        }

        if (page.HasValue && !pageSize.HasValue)
        {
            throw new ArgumentException("You have to define a pageSize if you specify a page!");
        }

        var entities = Process(filter, sorter, includer);

        if (page != null)
            entities = entities.Skip(pageSize.Value * page.Value);

        if (pageSize != null)
            entities = entities.Take(pageSize.Value);

        return entities;
    }

    public virtual int Count(IEntityFilter<TEntity> filter = null)
    {
        return Process(filter).Count();
    }

    public bool Any(IEntityFilter<TEntity> filter = null)
    {
        return Process(filter).Any();
    }

    public TEntity SingleOrDefault(IEntityFilter<TEntity> filter = null, IEntityIncluder<TEntity> includer = null)
    {
        return Process(filter, includer: includer).SingleOrDefault();
    }

    public TEntity Single(IEntityFilter<TEntity> filter = null, IEntityIncluder<TEntity> includer = null)
    {
        return Process(filter, includer: includer).Single();
    }

    public TEntity FirstOrDefault(IEntityFilter<TEntity> filter = null, IEntitySorter<TEntity> sorter = null, IEntityIncluder<TEntity> includer = null)
    {
        return Process(filter, sorter, includer).FirstOrDefault();
    }

    public TEntity First(IEntityFilter<TEntity> filter = null, IEntitySorter<TEntity> sorter = null, IEntityIncluder<TEntity> includer = null)
    {
        return Process(filter, sorter, includer).First();
    }

    public virtual TEntity Find(int id)
    {
        var entity = EntitySet.FirstOrDefault(x => x.Id == id);
        if (entity != null && entity.Deleted)
        {
            return null;
        }
        return entity;
    }

    public virtual void AddOrUpdate(TEntity entity)
    {     
        if (entity.Id == 0)
        {
            Add(entity);
        }
        else
        {
            Update(entity);
        }
    }


    public virtual void Delete(TEntity entity)
    {
        entity.Deleted = true;
        Update(entity);
    }

    public virtual void Delete(IEnumerable<TEntity> entities)
    {
        foreach (TEntity entity in entities)
        {
            Delete(entity);
        }
    }

    public virtual void Delete(int id)
    {
        TEntity entity = Find(id);
        if (entity != null)
            Delete(entity);
    }

    public virtual void HardDelete(TEntity entity)
    {
        DbEntityEntry entry = Context.Entry(entity);
        if (entry.State != EntityState.Deleted)
        {
            entry.State = EntityState.Deleted;
        }
        else
        {
            EntitySet.Attach(entity);
        }
    }

    public virtual void HardDelete(int id)
    {
        TEntity entity = Find(id);
        if (entity != null)
            HardDelete(entity);
    }

    public TResult Query<TResult>(Func<IQueryable<TEntity>, TResult> query)
    {
        return query(Entities);
    }

    /// <summary>
    /// Gets the queryable entities
    /// </summary>
    public IQueryable<TEntity> QueryableEntities
    {
        get
        {
            return _entitySet;
        }
    }

    protected virtual void Add(TEntity entity)
    {
        DbEntityEntry entry = Context.Entry(entity);
        if (entry.State != EntityState.Detached)
        {
            entry.State = EntityState.Added;
        }
        else
        {
            EntitySet.Add(entity);
        }
    }

    protected virtual void Update(TEntity entity)
    {
        DbEntityEntry entry = Context.Entry(entity);
        if (entry.State == EntityState.Detached)
        {
            EntitySet.Attach(entity);
        }
        entry.State = EntityState.Modified;


    }
}

當我啟動服務時,這是輸出


Starting service
**** CONTEXT CONSTRUCTED, HASH:63174400 ****
**** CONTEXT CONSTRUCTED, HASH:24275713 ****
**** CONTEXT CONSTRUCTED, HASH:34631232 ****
**** CONTEXT CONSTRUCTED, HASH:66590816 ****
**** CONTEXT CONSTRUCTED, HASH:24695352 ****
**** CONTEXT CONSTRUCTED, HASH:11985038 ****
*** Unit Of Work ContextHash: 63174400***
--------------------------------
Security service is running @ http://localhost/security

因此,經過更多的調試和測試后,我設法自己解決了這一問題。 這是我所做的和發現的事情:

我開始研究ninject范圍,並嘗試了所有可用選項,但沒有一個起作用。 下一步是跳過粘結劑類,並手動鏈接我的所有接口和實現。 起初這也不可行,所以我再次開始使用示波器設置。

我將整個工作與手動綁定在RequestScope中一起使用。 當然,手動綁定不是我想要的。

經過一些測試我有這個

    private static StandardKernel CreateKernel()
    {
        var kernel = new StandardKernel();

        ConfigurationAction scope = bind => bind.InRequestScope();

        /* this works*/
       scope(
            kernel.Bind(typeof(SecurityContext))
                .ToSelf());

        /*
         * This works
         * 
         * kernel.Bind(typeof(SecurityContext))
            .ToSelf()
            .InRequestScope();*/
        /*
         * This does not work
        kernel.Load(new ContextBinder(scope));
         */
        kernel.Load(new UnitOfWorkBinder(scope));
        kernel.Load(new RepositoryBinder(scope));
        kernel.Load(new ServiceBinder(scope));



        return kernel;
    }

我不知道為什么在contextbinder中綁定上下文會為它需要的每個實例創建一個單獨的上下文。 因此,如果有人可以澄清。

我將其標記為已解決,因為上面的代碼對我有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM