Настраиваемое управление временем жизни в контейнерах DI (wcf proxy: Unity vs Castle Windsor) - PullRequest
3 голосов
/ 06 июля 2010

Я нашел хороший пост: Singleton WCF Proxy .

Речь идет о реализации области жизни прокси WCF с использованием Castle Windsor DI контейнера.

Реализация абстрактного класса AbstractLifestyleManager из Castle.MicroKernel.Lifestyle пространства имен переопределяет 3 метода: Resolve, Dispose и Release. В методе Release у нас есть доступ к контексту , из которого мы можем разрешить экземпляр службы.

Я скопировал код из этого поста (с небольшим изменением) ниже:

public class SingletonWCFProxyLifestyleManager : AbstractLifestyleManager
{
    private object instance;

    public override object Resolve(Castle.MicroKernel.CreationContext context)
    {
        lock (base.ComponentActivator)
        {
            if (this.instance == null)
            {
                this.instance = base.Resolve(context);
            }
            else
            {
                ICommunicationObject communicationObject = this.instance as ICommunicationObject;
                if (communicationObject != null &&
                    communicationObject.State == CommunicationState.Faulted)
                {
                    try
                    {
                        communicationObject.Abort();
                    }
                    catch { }

                    this.instance = base.Resolve(context);
                }
            }
        }
        return this.instance;
    }

    public override void Dispose()
    {
        if (this.instance != null)
        {
            base.Release(this.instance);
        }
    }

    public override void Release(object instance)
    {

    }
}

Я бы хотел предоставить такую ​​же функциональность, используя контейнер Unity . Похоже, класс LifetimeManager из пространства имен Microsoft.Practices.Unity (и, опционально, интерфейс IRequiresRecovery) предназначен для этого.

Все методы, которые предоставляет класс, показаны ниже:

public class SingletonWCFProxyLifestyleManager : LifetimeManager, IRequiresRecovery  
{
   public override object GetValue()
   {
      throw new NotImplementedException();
   }

   public override void RemoveValue()
   {
      throw new NotImplementedException();
   }

   public override void SetValue(object newValue)
   {
      throw new NotImplementedException();
   }

   #region IRequiresRecovery Members   
   public void Recover()
   {
      throw new NotImplementedException();
   }    
   #endregion
}

А вот и вопрос:

Как обеспечить ту же функциональность во втором примере (с использованием Unity), как это было сделано в первом примере (с использованием Castle Windsor)?

(PS: нет доступа к контексту контейнера, так как я могу разрешить объект?).

Привет

1 Ответ

0 голосов
/ 06 июля 2010

Я постараюсь ответить на мой вопрос (надеюсь, что правильно ..).

Я нашел этот пост Написание пользовательских Lifetime Managers . Я пытался реализовать решение, которое подробно описал ранее, основываясь на этом посте и предыдущем: Singleton WCF Proxy .

Ниже то, что я создал. Конечно, я должен проверить этот код. На первый взгляд, это нормально, но я посмотрю позже.

public class SingletonWCFProxyLifestyleManager : LifetimeManager, IRequiresRecovery, IDisposable
   {
      private static readonly object _locker = new object();
      private Guid _key;

      public SingletonWCFProxyLifestyleManager()
      {
         _key = Guid.NewGuid(); 
      }

      public override object GetValue()
      {
         Monitor.Enter(_locker);
         object result = Storage.Instance.Get(_key);
         if (result != null)
         {
            ICommunicationObject communicationObject = result
                                                       as ICommunicationObject;
            //If the proxy is in faulted state, it's aborted and a new proxy is created
            if (communicationObject != null &&
                communicationObject.State == CommunicationState.Faulted)
            {
               try
               {
                  communicationObject.Abort();
               }
               catch
               {
               }

               Dispose();
               return null;   //Return before releasing monitor
            }
            Monitor.Exit(_locker);
         }
         return result;
      }

      public override void RemoveValue()
      {

      }

      public override void SetValue(object newValue)
      {
         Storage.Instance.Set(_key, newValue);
         TryToReleaseMonitor(); 
      }

      #region IRequiresRecovery Members

      public void Recover()
      {
         TryToReleaseMonitor();
      }

      #endregion

      private void TryToReleaseMonitor()
      {
         try
         {
            Monitor.Exit(_locker);
         }
         catch(SynchronizationLockException)
         {
         } // This is ok, just means we don't hold the lock
      }

      #region IDisposable Members

      public void Dispose()
      {
         object result = Storage.Instance.Get(_key);
         if (result != null)
         {
            try
            {
               Storage.Instance.RemoveAndDispose(_key);
            }
            catch
            {
               ICommunicationObject communicationObject = result as ICommunicationObject;
               if (communicationObject != null)
               {
                  communicationObject.Abort();
               }
            }
         }
      }

      #endregion
   }

Storage служебный класс был создан для кэширования экземпляров служб (он содержит хеш-таблицу и несколько служебных методов, например Get или RemoveAndDispose), но его слишком просто вставить сюда.

...