SORU
20 Mayıs 2010, PERŞEMBE


Birlik SynchronizationLockException her zaman değil atmak için yapılmış olabilir?

Birlik bağımlılık enjeksiyon konteyner SynchronizedLifetimeManager genellikle Monitör neden olur yaygın olarak bilinen bir sorun gibi görünüyor.Çıkış yöntemi sonra yakalandı ve göz ardı edilir hangi bir SynchronizationLockException atmak için. Bu bir sorun benim için çünkü sevdiğim için hata ayıklama Visual Studio ayarlamak için mola her atılan özel durum, bu yüzden her zaman benim uygulama başlar düşündüm bu durum birden çok kez için bir sebep yok.

Nasıl atılıyor bu durum önlenebilir?

Bu konular başka bir yerde web üzerinde nerede açıklanan, tavsiye genellikle hata ayıklayıcı ayarları görmezden değiştirerek içerir. Bu doktora gidip söylemeye benzer, "Doktor, kolumu kaldırınca ağrıyor, "Evet, kaldırma!"" dedi, Doktor. Bu durum ilk etapta atılan durduran bir çözüm arıyorum.

Özel durum GetValue ilk adlı varsayımını yapar çünkü, Monitör nerede Görüntülemek yöntemi oluşur.Girin denir. Ancak, LifetimeStrategy ve UnityDefaultBehaviorExtension düzenli olarak derslere GetValue çağırmadan Görüntülemek için Ara.

Yapmasam daha var değiştirmek için kaynak kodu ve korumak benim kendi sürümü Birlik, yani umut ediyorum bir çözüm ben de eklemek bir araya uzantıları, politikaları veya stratejileri için kabın olacak emin olun, Eğer ömrü yöneticisi bir SynchronizedLifetimeManager, GetValue her zaman aramadan önce başka bir şey.

CEVAP
30 HAZİRAN 2010, ÇARŞAMBA


Kod arama SynchronizedLifetimeManager yolları veya ContainerControlledLifetimeManager gibi bir torunu var eminim, ama bana sorun yaratıyor özellikle iki senaryo vardı.

İlk oldu benim hatam - ben kullanarak yapıcı enjeksiyon için bir başvuru kaynağı için kapsayıcı ve yapıcı olduğumu da ekleyerek yeni bir örneğini sınıfa konteyner için ileride kullanmak. Bu geriye doğru yaklaşım nesne bütünlüğünün GetValue denilen Görüntülemek için aradı aynı nesne değildi ki ContainerControlled için Geçici bir ömür boyu yöneticisi değiştirme etkisi vardı. Ders öğrendim-inşa sırasında hiçbir şey yapma, bir nesnenin ömrü yöneticisi değiştirebilir.

İkinci senaryo her zaman Registerİnstance denir, UnityDefaultBehaviorExtension aradığı ilk GetValue çağırmadan Görüntülemek için. Neyse ki, Birlik sorunu, yeterince kanlı fikirlilik ile çalışabilir genişletilebilir yeterli.

Böyle bir uzantı: yeni bir davranış ile başlayacak

/// <summary>
/// Replaces <see cref="UnityDefaultBehaviorExtension"/> to eliminate 
/// <see cref="SynchronizationLockException"/> exceptions that would otherwise occur
/// when using <c>RegisterInstance</c>.
/// </summary>
public class UnitySafeBehaviorExtension : UnityDefaultBehaviorExtension
{
    /// <summary>
    /// Adds this extension's behavior to the container.
    /// </summary>
    protected override void Initialize()
    {
        Context.RegisteringInstance  = PreRegisteringInstance;

        base.Initialize();
    }

    /// <summary>
    /// Handles the <see cref="ExtensionContext.RegisteringInstance"/> event by
    /// ensuring that, if the lifetime manager is a 
    /// <see cref="SynchronizedLifetimeManager"/> that its 
    /// <see cref="SynchronizedLifetimeManager.GetValue"/> method has been called.
    /// </summary>
    /// <param name="sender">The object responsible for raising the event.</param>
    /// <param name="e">A <see cref="RegisterInstanceEventArgs"/> containing the
    /// event's data.</param>
    private void PreRegisteringInstance(object sender, RegisterInstanceEventArgs e)
    {
        if (e.LifetimeManager is SynchronizedLifetimeManager)
        {
            e.LifetimeManager.GetValue();
        }
    }
}

Varsayılan davranışı değiştirmek için bir yol gerekir. Birlik belirli bir uzantısı kaldırmak için bir yöntem yok, her şeyi kaldırın ve tekrar geri diğer uzantıları koymak zorunda

public static IUnityContainer InstallCoreExtensions(this IUnityContainer container)
{
    container.RemoveAllExtensions();
    container.AddExtension(new UnityClearBuildPlanStrategies());
    container.AddExtension(new UnitySafeBehaviorExtension());

#pragma warning disable 612,618 // Marked as obsolete, but Unity still uses it internally.
    container.AddExtension(new InjectedMembers());
#pragma warning restore 612,618

    container.AddExtension(new UnityDefaultStrategiesExtension());

    return container;
}

UnityClearBuildPlanStrategies fark ettin mi? RemoveAllExtensions hariç politika ve stratejileri kabın iç listeleri temizler, başka bir uzantısı varsayılan uzantıları restore ettiğim zaman çiftleri ekleme önlemek için kullanmak zorunda kaldım:

/// <summary>
/// Implements a <see cref="UnityContainerExtension"/> that clears the list of 
/// build plan strategies held by the container.
/// </summary>
public class UnityClearBuildPlanStrategies : UnityContainerExtension
{
    protected override void Initialize()
    {
        Context.BuildPlanStrategies.Clear();
    }
}

Şimdi güvenle deliliğin eşiğine tahrik olma korkusu olmadan Registerİnstance kullanabilirsiniz. Sadece emin olmak için, burada bazı testler:

[TestClass]
public class UnitySafeBehaviorExtensionTests : ITest
{
    private IUnityContainer Container;
    private List<Exception> FirstChanceExceptions;

    [TestInitialize]
    public void TestInitialize()
    {
        Container = new UnityContainer();
        FirstChanceExceptions = new List<Exception>();
        AppDomain.CurrentDomain.FirstChanceException  = FirstChanceExceptionRaised;
    }

    [TestCleanup]
    public void TestCleanup()
    {
        AppDomain.CurrentDomain.FirstChanceException -= FirstChanceExceptionRaised;
    }

    private void FirstChanceExceptionRaised(object sender, FirstChanceExceptionEventArgs e)
    {
        FirstChanceExceptions.Add(e.Exception);
    }

    /// <summary>
    /// Tests that the default behavior of <c>UnityContainer</c> leads to a <c>SynchronizationLockException</c>
    /// being throw on <c>RegisterInstance</c>.
    /// </summary>
    [TestMethod]
    public void UnityDefaultBehaviorRaisesExceptionOnRegisterInstance()
    {
        Container.RegisterInstance<ITest>(this);

        Assert.AreEqual(1, FirstChanceExceptions.Count);
        Assert.IsInstanceOfType(FirstChanceExceptions[0], typeof(SynchronizationLockException));
    }

    /// <summary>
    /// Tests that <c>UnitySafeBehaviorExtension</c> protects against <c>SynchronizationLockException</c>s being
    /// thrown during calls to <c>RegisterInstance</c>.
    /// </summary>
    [TestMethod]
    public void SafeBehaviorPreventsExceptionOnRegisterInstance()
    {
        Container.RemoveAllExtensions();
        Container.AddExtension(new UnitySafeBehaviorExtension());
        Container.AddExtension(new InjectedMembers());
        Container.AddExtension(new UnityDefaultStrategiesExtension());

        Container.RegisterInstance<ITest>(this);

        Assert.AreEqual(0, FirstChanceExceptions.Count);
    }
}

public interface ITest { }

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Lupe Fiasco

    Lupe Fiasco

    23 ŞUBAT 2006
  • Moodle

    Moodle

    11 Mayıs 2010
  • Shameless Maya

    Shameless Ma

    24 Mayıs 2012