Поделиться через


Managed Extensibility Framework

Several months ago we formed what we call Application Framework Core team. The charter of the team is to play the same role in the application frameworks space (WinForms, ASP.NET, WPF, Silverlight) as the Base Class Libraries (BCL) team plays at the bottom of the platform stack.

The BCL team did a good job fulfilling the role of the team responsible for decreasing duplication and providing common abstractions for the low levels of the platform. Unfortunately, we did not have a similar team really focused on these sets of issues higher up on the stack. This resulted in some unfortunate duplication (like several data binding models for each of the application models, different dependency property system for WPF and WF) and lack of common abstractions (what undo APIs should my generic application plugin call?) for application model code. The Application Framework Core team is now in place to start addressing the problems.

One of the first concrete projects that we are working on and are ready to slowly talk about is what we call the Managed Extensibility Framework (MEF). We observed that there are more and more places in the .NET Framework itself and increasingly managed applications (like Visual Studio) where we want to provide, or already provide, hooks for 3rd party extensions. Think about TraceListener plugins for the TraceSource APIs, pluggable rules for Visual Studio Code Analysis (and the standalone FxCop), etc. In the absence of a built-in extensibility framework (like MEF), our developers who want to enable such extensions often are forced to create custom mechanisms, thus duplication. We hope that MEF will both stop such duplication and encourage/enable more extensibility in the Framework and applications built on top of it.

We will blog more details about MEF in the upcoming months, but here are some early details (subject to changes, of course): MEF is a set of features referred in the academic community and in the industry as a Naming and Activation Service (returns an object given a “name”), Dependency Injection (DI) framework, and a Structural Type System (duck typing). These technologies (and other like System.AddIn) together are intended to enable the world of what we call Open and Dynamic Applications, i.e. make it easier and cheaper to build extensible applications and extensions.

The work we are doing builds on several existing Microsoft technologies (like the Unity framework) and with feedback from the DI community. The relationship with the Unity team is the regular relationship between the P&P group and the .NET Framework group where we trickle successful technologies and ideas from the P&P team into the .NET Framework after they have passed the test of time. We have done this with some features in the diagnostics, exceptions, and UI space in the past. The direct engagement with the DI community is also starting. We gave a talk on the technology at last week’s MVP Summit, and talked with Jeremy Miller (the owner of Structure Map) and Ayende Rahien (Rhino Mocks) . We got lots of great feedback from Jeremy and Ayende and I think their experience in the DI space and their feedback will be invaluable as the project evolves. Thanks guys! We are of course also looking forward to engaging others in the DI community.

And finally here is some code showing basic scenarios our framework supports:

Creating an Extension Point in an Application:

public class HelloWorld {

  [Import] // import declares what a component needs

  public OutputDevice Output;

   public void SayIt() {

   Output.WriteLine("Hello World");

  }

}

// Extension Contract

public abstract class OutputDevice {

  void WriteLine(string output)

}

1. Creating an Extension

[Export(typeof(OutputDevice))] // export declared what a component gives

public class CustomOutput : OutputDevice {

  public void WriteLine(string output) {

    Console.WriteLine(output);

  }

}

 

2. Magic that makes composes (DIs) the application with the extensions.

var domain = new ComponentDomain();

var hello = new HelloWorld();

// of course this can be implicit

domain.AddComponent(hello);

domain.AddComponent(new CustomOutput());

domain.Bind(); // bind matches the needs to gives

hello.SayIt();

Expecting lots of questions, I will preemptively answer (J): we don’t yet know whether or when we will ship this. We do have working code and we are looking into releasing a preview/CTP of the technology. For now we would be very interested in high level feedback. What do you think hinders extensibility in frameworks and application? Where would you like the Framework to be more extensible? What DI framework features you need, like, want, and use on daily basis? i.e. is constructor injection required?

And lastly, we are hiring! :-)

Comments

  • Anonymous
    April 25, 2008
    Looking good - I've been waiting for such a thing to be available in the general framework for a long time :D To answer one of your specific questions, I think constructor injection is very much required, and I explain why here: http://blogs.msdn.com/ploeh/archive/2007/06/02/StateYourDependencyIntent.aspx.

  • Anonymous
    April 25, 2008
    First of all constructor injection is a must for me also. One thing that I don't like is that I have to clutter my classes with attributes to use your DI container. You should at least have a way to make this optional. My classes shouldn't depend in any way on the DI container used. Take a look at how other DI containers handle this. Also please provide good extensibility points to the DI container itself and make it easy to unit test. If you want to do it right, take a look at how the ASP.NET MVC team has done it. Listen to the community, look at other projects in this domain, ship early and often, make it easy to test, extend or even replace. If you keep this in mind, this could become useful. Thanks.

  • Anonymous
    April 25, 2008
    Fantastic news. It is important that these extensions can be added and removed/replaced at runtime and also able to run at full performance. The current approach to making extensions unloadable by using separate AppDomains results in too much of a performance-hit if there is a lot to serialize across the AppDomain boundary. I look forward to hearing more about this as you progress.

  • Anonymous
    April 25, 2008
    I think that constructor injection is absolutely necessary (I use Castle at the moment). If it is not available, I probably would not use MEF. Overall, I am quite disappointed by the default public constructor requirement in a lot of places within framework (why can't all things like JSON serialization just use TypeConverter.CreateInstance). It makes class much less maintainable, since there is not static way to check it got all dependencies.

  • Anonymous
    April 26, 2008
    Krzysztof, From your prospective, what makes dependency injection better than some of the existing patterns (such as ProviderBase)? How would adding attribute-based dependency injection affect usability of the .NET framework? For example, one could argue that the following example is comparable in flexibility but easier to understand and debug. <code><pre> public class HelloWorld {   public void SayIt() {      Console.WriteLine("Hello World");  } } // Service Contract public static Console {   private static TextWriter _out;   public static void WriteLine(string s) {      _out.WriteLine(s);   }   // Injection Point   public static void SetOut(TextWriter out) {      _out = out;   } } // Provider Contract public abstract class TextWriter {   public virtual void WriteLine(string s); } // Concrete Provider public class StringWriter : OutputDevice {   private StringBuilder _sb;   public override void WriteLine(string s) {      _sp.Append(s);   } } // There is no magic Console.SetOut(new StringWriter()); var hello = new HelloWorld(); hello.SayIt(); </pre></code> Although more verbose, with a simple code generation tool (perhaps based on T4), this example could be as easy to implement as the example with attribute-based dependency injection. What do you think? Thanks.

  • Anonymous
    April 26, 2008
    The comment has been removed

  • Anonymous
    April 27, 2008
    I saw Kit's demo at recent MVP summit and was great but, how does this fit with System.AddIn?

  • Anonymous
    April 27, 2008
    Very interesting post over here.

  • Anonymous
    April 27, 2008
    Please don't forget code implemented in DLR-based languages, which often can't use attributes, provide constructors or be loaded directly from an assembly.  The most generic way to supply an object-creation function is through a delegate.

  • Anonymous
    April 27, 2008
    I think that Constructor Injection is absolutely required because it allows you to strictly define the object dependencies and abstracts you from a particular DI system. I can therefore write a class that will support DI with CastleWindors, Unity etc. Use of attributes should be a last resort. Also, why reinvent the pattern? IUnityContainer container = new UnityContainer(); container.RegisterType<CustomOutput>(); var hello = container.Resolve<HelloWorld>(); hello.SayIt();

  • Anonymous
    April 28, 2008
    Here is my wishlist :) Total transparancy is number one for me. I should be able to use existing code with a DI framework, no recompile or change needed. This includes existing .NET framework code. So I would at least need transparent constructor and property injection, and a way to assign factory objects through a delegate/method, specify singleton. transparent also means that it should work with all the different hosts like ASP.NET, ClickOnce, NT Services, etc. Anything else simply won't do. What also needs to be totally transparent is the errors you inevitably make in configuring the DI framework. Nothing worse than going through attributes or xml config to finally find a typo somewhere because the stacktrace gives you too little info. You need proper exception handling with human readable description of the reason why it doesnt work. The configuration should be validatable/checked for errors before running your application to limit this happening, hooking this into compilation of code would be great. Configuration should be possible through XML and programmatic interface. (Configuration should obviously be extensible and replaceable with other implementations) As for programmatic interface I would like two flavours, standard .NET (inside the executing program) and DSL scripting interface (outside of the executing program, comparable to XML configuration) for instance a DLR language or a less verbose CLR language like boo. In my opinion a framework is partly as good as the tools it comes with. The configuration should have an 'editor' of sorts in Visual Studio, (checkout spring ide, its got some nice features on the java side). Even better would be if you could configure and connect the objects you want through some kind of class browser and select your output for configuration. the better you get this part down, the easier it will be to adopt. Other than that I would like lifecycle management, hooks for creation and cleanup, a facility like extension model like Windsor Castle has, custom XML schema extensions like spring and an easy way to provide plugins through DI and the  possibility to assign separate Appdomains for the plugins would be great as well.

  • Anonymous
    April 28, 2008
    This seems very cool, but I have concerns regarding usability. How is it intended to be used in larger projects?

  • Anonymous
    April 28, 2008
    I don't mind Constructor Injection but I've always preferred Property (Setter) Injection or eve Method Injection but that's because I like to drive the design I make using my interfaces - which makes .ctor injected dependencies 'invisible' to me. Not saying you should ban CI - not at all! I just wanted to voice the opposite opinion in this torrent of praise for this one type of injection. ;~) That's my €0.02.

  • Anonymous
    April 28, 2008
    We use our own IoC/DI framework.   I think standardizing on the (optional) attributes is a good thing.  This way other frameworks can use these same attributes. Not sure about the .Bind() idea - binding consumers and providers of services is often much more complicated than the 1:1 relationship that this implies. Also, DI is all about the configuration.  What about setting properties using reflection?  What about a standard container?  or container interface?

  • Anonymous
    April 28, 2008
    The comment has been removed

  • Anonymous
    April 28, 2008
    Invent, invent, invent :(

  1. Why not simple reuse of other framework like Unity / Spring?
  2. Dont forget about configurable (as opposed to programmable)
  3. I read it and wansn't amazed, everything was already done by other framework - did i miss anything?
  • Anonymous
    April 28, 2008
    The comment has been removed

  • Anonymous
    April 28, 2008
    Thanks for all the great feedback. It will really help us weigh the pros and cons of the two main design issues: constructor injection and the attribute based programming model. We have had many discussion about these two internally, and there are interesting tradeoff we would need to make to add these two features. I will try to erite about the tradeoffs (or ask somebody on the team to do it) to start a focused discussion about these two. Thanks again for the feedback. It's all great!

  • Anonymous
    April 28, 2008
    Ran, We want to use it for extensibility of the Framework itself and Visual Studio. We cannot use Unity or Spring for this.

  • Anonymous
    April 28, 2008
    @Oleg My biggest issue with this is I expect Console.WriteLine to write to the Console, not some other stream (unless the console is being redirected to a file, which is standard behaviour).  OutputDevice only implies the input will go to some device.  Could be the console, a printer, a network stream, etc... @Krzysztof Performance is critical. I'd also like to see the attributes in a non-specific namespace, so other DI frameworks could use the same metadata.  Ideally this would be general enough for any DI and/or IoC framework to consume.  In the past, I have had mixed feelings about using attributes within one's code for the DI / IoC framework; however, I now believe it to be necessary.  Why?  Primarily from a discoverability point of view - I want to be able to use a generic tool to examine an assembly and identify the dependencies.  Configuration is great, but it is very difficult to determine the original engineer's intent without the attributes.  From your example above, it is easy for me to see (given the presence of the [Import] attribute) that the Output property should be injected / provided externally.  Without the attribute (and being purely configuration based) how do I know this?  I now have to look elsewhere, making experimentation difficult. Cheers, Stuart Carnie

  • Anonymous
    April 28, 2008
    Personally, I'd REALLY this to look more like structured typing. I'm pretty much over Attributes and would prefer a way to do DI without Attributes.

  • Anonymous
    April 28, 2008
    Sounds awesome!  I've had to duplicate lots of effort from project to project that requires extensibility of some sort and so can't wait to see what you and the rest of the team cook up.   Thanks, Kevin Impacta LLC (http://www.impactalabs.com)

  • Anonymous
    April 28, 2008
    constructor Injection --> a big YES attributes based mechanism --> a big NO

  • Anonymous
    April 28, 2008
    Sounds very promising in general, but ... What I still don't get here actually is: What do we have here in addition to using Unity with System.AddIn? Can you put together more explanation about this please? i think it's a FAQ too :).

  • Anonymous
    April 28, 2008
    Re: Spring.Net as a way of getting where you are trying to go.   Perhaps you should think of Spring.Net as going to far in terms of complexity and performance hit - and trying for a target well inside that extreme.   Also, why the "bind"?  Unless you are trying for a lazy injection or have order of injection issues, it would be great to avoid the "bind" entirely.  

  • Anonymous
    April 28, 2008
    The comment has been removed

  • Anonymous
    April 29, 2008
    I'll throw a vote in for Compact Framework support in the initial release, but that's probably wishful thinking.

  • Anonymous
    April 29, 2008
    The comment has been removed

  • Anonymous
    April 29, 2008
    I will have to agree with the other commenters who want constructor injection.  Initially Attributes were appealing and in many cases I still use them but for DI related functionality I much perfer constructor injection.  Please do not bake in a dependency on attributes for this scenerio.

  • Anonymous
    April 30, 2008
    You've been kicked (a good thing) - Trackback from DotNetKicks.com

  • Anonymous
    April 30, 2008
    The comment has been removed

  • Anonymous
    April 30, 2008
    The single biggest factor for success on any project I have been apart of in the last 10 years at Microsoft

  • Anonymous
    May 01, 2008
    The comment has been removed

  • Anonymous
    May 01, 2008
    微软建立了一个应用程序框架核心(ApplicationFramework Core)团队,以减少WCF、WPF以及ASP.NET之间的重复。这个团队的目标是为了避免一些设计上的问题,例如WPF与W...

  • Anonymous
    May 04, 2008
    Personally, I feel you should create a (DI) Container Provider, and then provide a concrete Unity implementation. Microsoft.Mef.Container Microsoft.Met.Container.Unity Others can create their own concrete implementations too (i.e. Spring etc.). Microsoft.Mef.Container.Spring This is exactly what I did when I customized Prism for my needs.  And by Provider I mean the one which inherits from ProviderBase, and is specified in a corresponding config section.  Not the loose interpertation of the term as Prism currently implements.

  • Anonymous
    May 11, 2008
    Attributes = No, Autowiring = Yes

  • Anonymous
    May 11, 2008
    I expect all of these maps of dependencies and contributions to be fully dynamic right? Attributes are fun for the demo and simpler apps but are severely limiting for many scenarios. Id like to see evidence of thinking of contributions and dependencies in  beyond object references... e.g. event hookups, etc etc. Good luck and keep up the good work~!

  • Anonymous
    May 13, 2008
    Just lately there seems to be a veritable feast of new blog stuff about VSX (if you don't mind me switching

  • Anonymous
    May 13, 2008
    What do you guys think about dynamic activation / deactivation of components coupled with a concept of mandatory / optional extension points: static void Main(string[] args) {    var domain = new ComponentDomain();    var hello = new HelloWorld();    // of course this can be implicit    domain.AddComponent(hello);    domain.AddComponent<OutputDevice>(new CustomOutput());    domain.AddComponent<MessageProcessor>(new TruncateProcessor(2));    domain.Bind();           // bind matches the needs to gives    hello.SayIt("Hello");    // => "He"    domain.DisableComponent<MessageProcessor>();    hello.SayIt("Hello");    // => "Hello"    domain.EnableComponent<MessageProcessor>();    hello.SayIt("Hello");    // => "He" } [Extensible] public class HelloWorld {    [ExtensionPoint(typeof(OutputDevice),        ExtensionPointImportance.RequiredExtension)]    public OutputDevice Output;    [ExtensionPoint(typeof(OutputDevice),        ExtensionPointImportance.OptionalExtension)]    public MessageProcessor Processor;    public void SayIt(string message)    {        string output = message;        output = Processor.Process(output);  // Here some magic must happen internally if the extension was not provided or is not active :o/ lol        Output.WriteLine(output);    } } // Extension Contract [ExtensionContract] public abstract class OutputDevice {    public abstract void WriteLine(string output); } [ExtensionContract] public abstract class MessageProcessor {    public abstract string Process(string input); } [Extension] public class CustomOutput : OutputDevice {    public override void WriteLine(string output)    {        Console.WriteLine(output);    } } [Extension] public class TruncateProcessor : MessageProcessor {    private int truncateLength;    public TruncateProcessor(int truncateLength)    {        this.truncateLength = truncateLength;    }    public override string Process(string input)    {        return input.Substring(0, truncateLength);    } } Crazy idea ? :)

  • Anonymous
    May 14, 2008
    The comment has been removed

  • Anonymous
    May 18, 2008
    【原文地址】 Managed Extensibility Framework 【原文发表日期】 28 April 08 06:14 Krzysztof 最近在他的blog上宣布 ,我们已经开始致力于为

  • Anonymous
    May 31, 2008
    Krzysztof recently announced on his blog that we have begun working on an extensibility framework for

  • Anonymous
    June 01, 2008
    My name is David Kean and I&#39;m a software developer at Microsoft in Redmond. There I work on the Managed

  • Anonymous
    June 03, 2008
    After accidentally losing my last personal domain and blog to an ‘advertising’ company that has now become

  • Anonymous
    June 04, 2008
    I&rsquo;m pleased to announce that we&rsquo;ve just released a Community Technology Preview (CTP) of

  • Anonymous
    June 04, 2008
    Congratulations to the MEF (Managed Extensibility Framework) team who just released their first CTP!

  • Anonymous
    June 04, 2008
    Today was a big day for my team because we released the bits for the first CTP of the Managed Extensibility

  • Anonymous
    June 04, 2008
    There is TechEd in Orlando, and this means, that there are a lot of new announcements. Let’s fill up

  • Anonymous
    June 04, 2008
    There is TechEd in Orlando, and this means, that there are a lot of new announcements. Let’s fill up

  • Anonymous
    June 05, 2008
    Wow.... I´m developing with my team a similar solution for mobile devices (.NETCF). But we have some differences. First we develop a really compact DI container. In our case we have all the metadata in different xml's, each module has several XML's (similar to OSGi). This XML's of the module declare the inputs and outputs, of the module. The module also declares which inputs it needs, and we add a new concept that is the state of the input. Now each developer develops his module with the corresponding XML. Now we are building an Application designer in which where the user select’s which modules will be include in the final application. The designer checks all the dependencies are correct, and then we compile this xml in a CF dll, for performance issues (with codeDom). An then all dynamic injection is done in runtime between modules :). It’s great this will be include in .NET Framework.! We will see the progress of this project. Count with us for testing, and comments form Argentina! Regards, Mariano Vicario

  • Anonymous
    June 05, 2008
    Several members of my team have already spilled the beans, but yes (!) we just released our first public

  • Anonymous
    June 07, 2008
    Krzysztof Cwalina announced that Microsoft has released a CTP of its Managed Extensibility Framework

  • Anonymous
    June 10, 2008
    The comment has been removed

  • Anonymous
    June 10, 2008
    Eric, I happy to engage in a discussion, as you might be pointing to good issues. The problem with the comment above is that it does not have enough concretes for me to respond, i.e. acknowledge or defend. For example, I did say that we are thinking about supporting POC, and so I don't understand how it implies that "everything new should somehow be more complex", why do you think that usage of attributes is a proof that it's not thought through, what are the 5 ways of doing the same thing in System namesapce?

  • Anonymous
    June 11, 2008
    The comment has been removed

  • Anonymous
    June 17, 2008
    · Everything You Wanted To Know About MVC and MVP But Were Afraid To Ask · Functional Programming in

  • Anonymous
    July 16, 2008
    About three months ago, we were on the heels of shipping Prism (Composite Application Guidance). At that

  • Anonymous
    July 16, 2008
    About three months ago, we were on the heels of shipping Prism (Composite Application Guidance). At that

  • Anonymous
    July 16, 2008
    About three months ago, we were on the heels of shipping Prism (Composite Application Guidance). At that

  • Anonymous
    July 16, 2008
    Krzysztof, I have written a lot of classes that use constructor injection. I would ideally like a DI system that I can introduce with a minimum of code change. Why should my classes have a dependency on a particular DI system via Import/Export attributes?

  • Anonymous
    July 16, 2008
    While eating my lunch I was running through google reader and started reading a post from Glen , this

  • Anonymous
    July 17, 2008
    Winston, I am trying to find some time to post about the attributes, but it's hard given my upcomming vacations and the need to finish 2nd edition of FDG. But quickly, we want to support attributes for the following reasons:

  1. We want reusable assemblies with dependencies to be "reflective", i.e. to advertize what dependencies they have and need to be able to run succesfully.
  2. We want to support classic application add-in scenarios (possibly in addition to the callsic DI scenarios). In application add-in scenarios the add-ins need to be smart and know how to compose themselves (i.e the app user just drops an assembly to a foolder). In the classic Di scenarios, the developer does the composition. We are currently investigating how to support the classic DI scenarios (were we do understan develoers don't want to apply attributes).
  • Anonymous
    July 20, 2008
    I have to say that my last year at Microsoft has been a little strange. Since the Acropolis project,

  • Anonymous
    July 25, 2008
    Pingback from http://www.truewill.net/myblog/index.php/2008/07/25/a_house_divided

  • Anonymous
    August 30, 2008
    The comment has been removed

  • Anonymous
    September 22, 2008
    The comment has been removed

  • Anonymous
    September 23, 2008
    The comment has been removed

  • Anonymous
    September 25, 2008
    It's not IoC, It's not MAF, it's not the Manged Entity Framework either :-) So what is it ? There has

  • Anonymous
    September 25, 2008
    It&#39;s not IoC, It&#39;s not MAF, it&#39;s not the Manged Entity Framework either :-) So what is it

  • Anonymous
    September 25, 2008
    It&#39;s not an IoC container, It&#39;s not MAF, it&#39;s not the Managed Entity Framework either :-

  • Anonymous
    September 25, 2008
    It&#39;s not an IoC container, It&#39;s not MAF, it&#39;s not the Managed Entity Framework either :-

  • Anonymous
    September 27, 2008
    九月初,微软在CodePlex推出了 Managed Extensibility Framework http://www.codeplex.com/MEF 托管扩展性框架是什么? &ldquo;托管扩展性框架

  • Anonymous
    November 06, 2008
    The Managed Extensibility Framework (MEF) is a new feature of .NET 4 (and will work on 3.5 as well) that

  • Anonymous
    November 07, 2008
    The Managed Extensibility Framework (MEF) is a new feature of .NET 4 (and will work on 3.5 as well) that

  • Anonymous
    November 20, 2008
    Your Story is Submitted - Trackback from DotNetShoutout