开发者

Using 'System.Lazy.LazyThreadSafetyMode' with MEF

开发者 https://www.devze.com 2023-02-01 08:58 出处:网络
I import many parts from different assemblies into my class like this: [ImportMany(typeof(IServiceProvider))]

I import many parts from different assemblies into my class like this:

[ImportMany(typeof(IServiceProvider))]
private IEnumerable<Lazy<IServiceProvider, IDictionary<string, object>>> ServiceProviders
   {
       get;
       set;
   }

After parts imported, Service providers are created on demand:

private IServiceProvider GetServiceProvider(String name)
{
    foreach (var serviceProvider in ServiceProviders)
    {
        String currentName = (String)serviceProvider.Metadata["Name"];
        if (currentName == name)
            return serviceProvider.Value; // Many threads receive here and try to create new instance.
    }

    return null;
}

As I commented in above code, many threads try to get value of the lazy variable (create new instance of it, if not created yet) at the same time.

Lazy<T>has a constructor which allow to create instance (value) in a thread-safe manner, like this:

// Something here...
Dictionary<string, object> metadata = new Dictionary<string,object>();
metadata.Add("Name", "test");
Lazy<IServiceProvider, IDictionary<string, object>> serviceProvider = new Lazy<IServiceProvider, IDictionary<string, object>>(ServiceProviderValueFactory, metadata, System.Threading.LazyThreadSafetyMode.ExecutionAndPublication);
// Now access to 'serviceProvider.Value' creates an instance (if not created yet) in a thread-safe manner.

private IServiceProvider ServiceProviderValueFactory()
{
    // Create and return a new instance of 'IServiceProvider'.
}

MEF take cares of object creation when importing parts and I want to use the Lazy constructor which allows开发者_如何学编程 for thread-safe value creation but I don't know how.


When creating your CompositionContainer, pass isThreadSafe=true to the constructor.

Note that it's not safe to do any recomposition in a thread-safe container, so you shouldn't use catalogs that change, or CompositionBatch, or the AttributedModelServices.ComposeParts() extension method.


I'm not convinced this is something you can change. The Lazy<T, M> type is initialised through the ExportServices internal class, and cannot be overridden. If you subclassed ExportProvider the target GetExports or GetExportsCore that return Lazy<T, M> are not abstract or virtual so cannot be overridden.

In ExportServices, it is hard coded as:

return new Lazy<T, M>(..., LazyThreadSafetyMode.PublicationOnly);
0

精彩评论

暂无评论...
验证码 换一张
取 消