I have a Winforms application that is designed to integrate with external software packages. This application reads data from these packages and pushes it to our server where users log in and use our application (App).
public abstract ClassToImplement
{
public abstract void DefinedMethod1();
public abstract void DefinedMethod2();
}
When we designed the application it was intended to do 95% of the integration work with the remaining 5% (implementation class / App2) being developed by a consultant who's familiar with the 3rd party software.
public class Implemented : ClassToImplement{
public override void DefinedMethod1(...);
public override void DefinedMethod2(...);
}
The "App" outputs a Class Library which is then referenced in the Implementation (App2). In our design we created an Abstract Class and defined the methods. The idea was that the consultant would download the repo for the implementation class and include the App as a reference. They would then write the necessary code for the methods they're implementing, compile and "voila!"
For obvious reasons I don't want to share the source project with external developers, otherwise I'd just share the full solution and use a single app, and, while I know they can see a lot with the DLL reference, it is just easier for us to control everything.
The problem comes with App: the main application algorithm needs to instantiate the implementation class and then the program runs perfectly.
in Form1.cs of App:
ClassToImplement impObj = new Implemented();
impObj.DefinedMethod1();
impObj.DefinedMethod2();
The challenge I'm having is that I cannot build "App" to output a DLL without instantiating the Class. I cannot instantiate the Implemented Class as I haven't got the code (yet).
It would be great to know how to go about achieving this sort of abstraction with a dependancy on (yet) unwritten code and also, what is the technical term for what I'm trying to do?
To make it just "work" use a Func which returns an instance of the abstract class.
In your secret repo:
//Your "App" DLL Project
public abstract class ClassToImplement
{
public abstract void DefinedMethod1();
public abstract void DefinedMethod2();
}
public class App : Form
{
public App(Func<ClassToImplement> initiator)
{
InitializeComponent();
ClassToImplement ci = initiator.Invoke();
ci.DefinedMethod1();
ci.DefinedMethod2();
}
}
//This is in a separate project which will be your startup project internally
public class Dummy : ClassToImplement
{
public override void DefinedMethod1(){}
public override void DefinedMethod2(){}
}
public class Program
{
public static void Main()
{
Application.Run(new App(()=> new Dummy()));
}
}
In the repo shared with the consultant:
// In the repo which is shared with the consultant
// This will be the startup project on the build server, and when the consultant is testing.
public class Implementation : ClassToImplement
{
public override void DefinedMethod1(){}
public override void DefinedMethod2(){}
}
public class Program
{
public static void Main()
{
Application.Run(new App(()=> new Implementation()));
}
}
On your build server, you can pull from both the repos, and set the startup project as the one given to the consultant. But when you are testing and developing internally, you set the startup project to your version with an implementation that does nothing.
As a side note, if you think what you are doing needs to be protected from consultants who have signed a confidentiality agreement, make sure to obfuscate when you do a release.
This is a two-step process usually:
Locate and load the assembly/dll:
Assembly assembly = Assembly.LoadFrom(DLL);
Instantiate the implemented class:
Type type = assembly.GetType(FullNameOfImplemented);
AppInstance = (ClassToImplement)Activator.CreateInstance(type, parameters);
The process you are looking for is often called stubbing. In this case you've chosen to encapsulate the integration functionality in a library, not web services, but the principle is the same.
The idea was that the consultant would download the repo for the implementation class and include the App as a reference.
This sounds like you've got the dependency relationship the wrong way round. If the consultant's code references your app, then your app can't reference it - it'd be a circular dependency. Instead, factor your app something more in line with the following:
App
|
|
App.Integration.Contracts
^ ^
| |
| App.Integration.Stub
|
App.Integration
The abstract class - it could just as easily be an interface in C# - resides in the Contracts assembly. This is the only compiled dependency your application has. Then at runtime use configuration to load either the stub, or the full implementation using an IoC container. An example is Unity for which you will need its configuration API. Reference the true type to use in the configuration file and change only that to update your application to use the full functionality.
First off I think you need to implement a proper plugin system if you dont want to share your code with that other developers.
Second you should code against your interface and not against its implementation. First because you dont have it and second because you may want to switch implementations for different 3rd party software.
If you need an instance for testing or stuff, you can use a handwritten mock or an mocking framework. If you need a real instance later on (when the other developers have delivered) you can use some design pattern like factory pattern or others for the creation. Try to avoid the new keyword if you want to change implementations later on.
Related
I am trying to create tools for a game to learn, as well as improve my own playing experience.
The primary .NET assembly, csass.dll, that controls the client is heavily obfuscated, and I have no control over this .dll-file at all and reading it's code is very time consuming. The game also includes a mainapi.dll which handles the communication between server and client. I have full control over this assembly and I can listen to the servers responses and send my own requests, which already gives me some pretty nice functionality, however there are some limitations I'd like to work around.
csass.dll references mainapi.dll, by default mainapi does not reference csass. In csass.dll there is a class, let's call it clickHandler, that has a public, non-static method ClickObj() of return type void. I want to call this method from within mainapi.dll, but I have no idea how to go about this, given that I have to leave csass.dll untouched.
Are there any feasible ways to 'retrieve' a clickHandler object (to then call its ClickObj() method) from within the mainapi assembly, without making any changes in csass.dll? Appreciate any and all input!
Create an interface:
public interface IClickHandler
{
void ClickObject();
}
Now create a helper class implementing that interface:
using CsAss;
public class ObjectClicker : IClickHandler
{
CsAss _csass;
public ObjectClicker(CsAss csass)
{
_csass = csass;
}
public void ClickObject()
{
_csass.clickObject();
}
}
Add a dependency on an instance of the interface into your MainAPI class:
public class MainApi
{
IClickHandler _clickHandler;
public MainApi(IClickHandler clickHandler)
{
_clickHandler = clickHandler;
// Now you have a class that can call the click handler for you
}
}
Now wire it all up:
public void StartupMethod()
{
var csass = new CsAss();
IClickHandler clickHandler = new ObjectClicker(csass);
var main = new MainApi(clickHandler);
// TODO: Start your app now that MainApi is properly configured
}
That last step is the only potentially tricky part, depending on your project layout. You need something that can create an instance of CsAss, MainApi and ObjectClicker. Normally I would solve that with the dependency injection (DI) pattern, either using a framework such as Autofac or so-called "poor man's DI" by manually instantiating from a central startup method. That gets a little more difficult with Unity since there isn't an easily accessible startup point. You could start looking into https://github.com/svermeulen/Zenject and go from there for options.
I'm trying to merge plugins library projects into a single one (for example, Location + PhoneCallTask). It works perfectly with wp7, but I get an unhandled exception with monodroid:
Could not load file or assembly 'Cirrious.MvvmCross.Plugins.Location.Droid.dll'
Of course, the location plugin is referenced in 'Cirrious.MvvmCross.Plugins.Droid.dll', the merged library.
Is there a way to point to the merged library path?
Having considered your question more fully...
I'm still not entirely sure what a merge plugin is, but I think the problem you are seeing must be down to the way that MvvmCross-MonoDroid uses file conventions to load plugins while all the other platforms force the user to provide explicit factory methods for each plugin.
The reason for this difference is because the file conventions are (IMO) the nicest way of doing this... but all the other platforms put security and/or compilation issues in the way which meant that alternative mechanisms had to be used...
The easiest thing for you to do is probably to switch the setup of your MonoDroid app to use the loader conventions too.
To do this:
in Setup.cs override CreatePluginManager() to:
protected override IMvxPluginManager CreatePluginManager()
{
var toReturn = new MvxLoaderBasedPluginManager();
var registry = new MvxLoaderPluginRegistry(".Droid", toReturn.Loaders);
AddPluginsLoaders(registry);
return toReturn;
}
and then provide a AddPluginsLoaders() implementation like:
protected virtual void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
{
loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Visibility.Droid.Plugin>();
loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Location.Droid.Plugin>();
loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Phone.Droid.Plugin>();
loaders.AddConventionalPlugin<AlphaPage.MvvmCross.Plugins.Mega.Droid.Plugin>();
// etc
}
Short answer:
I'm guessing you need to:
check that your namespaces and assembly names are all of the same convention
check that you have referenced both the core plugin assembly and the correct plugin implementation within the UI.Droid project
Longer answer (based on some notes I already had - will be published soon):
If you were to build an entirely new plugin, then you would:
1. Create a central shared plugin
This would be Portable Class library - say AlphaPage.MvvmCross.Plugins.Mega
Within that central shared PCL, you would put whatever portable code was available - often this might only be a few service Interface definitions - e.g.
public interface IAlphaService { ... }
and
public interface IPageService { ... }
You'd then add the PluginManager for that plugin which would just add the boiler-plate of:
public class PluginLoader
: IMvxPluginLoader
, IMvxServiceConsumer<IMvxPluginManager>
{
public static readonly PluginLoader Instance = new PluginLoader();
#region Implementation of IMvxPluginLoader
public void EnsureLoaded()
{
var manager = this.GetService<IMvxPluginManager>();
manager.EnsureLoaded<PluginLoader>();
}
#endregion
}
2. Create the specific plugin implementations
For each platform, you would then implement the plugin - e.g. you might implement AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone and AlphaPage.MvvmCross.Plugins.Mega.Droid
Within each of these you will implement the native classes which provide the services:
public class MyAlphaService : IAlphaService { ... }
and
public class MyPageService : IPageService { ... }
Finally each plugin would then provide the boilerplate plugin implementation:
public class Plugin
: IMvxPlugin
, IMvxServiceProducer
{
#region Implementation of IMvxPlugin
public void Load()
{
// alpha registered as a singleton
this.RegisterServiceInstance<IAlphaService>(new MyAlphaService());
// page registered as a type
this.RegisterServiceType<IPageService, MyPageService>();
}
#endregion
}
3. Instantiation of plugins
Each UI client will have to initialise the plugins.
This is done by the end UI client adding library references to:
the shared core plugin
the appropriate plugin implementation
3.1 WinRT, WindowsPhone and MonoTouch
Then, for WinRT, WindowsPhone and MonoTouch clients, you also need to provide a Loader accessor in setup.cs - like:
protected override void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
{
loaders.AddConventionalPlugin<AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone.Plugin>();
base.AddPluginsLoaders(loaders);
}
Note that Convention is used here - so it's important that AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone.Plugin implements the WindowsPhone plugin for AlphaPage.MvvmCross.Plugins.Mega.PluginLoader
3.2 MonoDroid
For MonoDroid clients, you don't need to add this setup step - because MonoDroid has less Assembly.Load restrictions than the other platforms - and ao can load the plugins from file. But for this to work, it's important that the assembly names match - if the PluginLoader is AlphaPage.MvvmCross.Plugins.Mega.PluginLoader then the conventions will try to load the plugin from AlphaPage.MvvmCross.Plugins.Mega.Droid.dll
4. Use of plugin services
After this setup, then applications should finally be able to access the plugins by:
adding a reference the Shared core portable library
at some time calling AlphaPage.MvvmCross.Plugins.Mega.PluginLoader.Instance.EnsureLoaded()
then accessing the individual services using this.GetService<IAlphaService>() or this.GetService<IPageService>()
5. Pure portable plugins
Some plugins can be 'pure portable'
In this case they don't need any specialization for each platform, and no step 3 is required.
For an example of this, see the Json implementation - https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins/Json
I am designing a simple plugin framework a for a .NET 3.5 application (WinForms).
Our current application needs to start supporting dynamic loading and "hooking" of different "plugins" / "extensions" that are unknown to the application at compile time.
These extensions would be "hooked" into different areas of the application, such as aded as event handlers of certain classes.
For example (simplified):
public class SomeSystem
{
public event Action<string> Completed;
public event Action<string> Failed;
public event Action<string> Stopped;
}
One use case I'd like to have is for developers to be able to define handlers for such events in a plugin assembly, without having the application know about them.
From my knowledge, IoC containers allow dynamically discovering objects at runtime and registering them in a container.
Is an IoC container able to also do this hooking into various events for me? Or is this task easier to do without such a framework?
How does one go about designing how to integrate an IoC container for such a task? (suppose that there are multiple extension points, such as different events that can be used to register on).
Some questions i found myself asking :
Is it common that the plugin itself offer a Register method to do the registration?
Should the IoC do the registration? (how is that usually done?)
How can extension points be easily defined when using an IoC container ?
You probably want to look at MEF. It allows all of the things you have asked about. The terminology it uses (ComposableParts, Exports, etc) is initially confusing, but it's very straightforward to use.
Is it common that the plugin itself offer a Register method to do the
registration?
MEF makes the application do the work of finding and registering plugins. The plugin only needs to implement an interface that states "I am a plugin that can do X".
Should the IoC do the registration? (how is that usually done?)
An application that will consume MEF plugins is able to specify how it will load the plugins. This could be by searching a directory for DLLs, reading the configuration file for a list of assembly names, checking the GAC - anything at all. It's totally extensible (in that you can write your own search classes)
How can extension points be easily defined when using an IoC container
?
MEF uses interfaces to define a Contract between the application and plugin.
This answer will be specific to my container.
Our current application needs to start supporting dynamic loading and "hooking" of different "plugins" / "extensions" that are unknown to the application at compile time.
To be able to do that you have to define some extension interfaces which you place in a class library which will be shared between your application and all of your plugins.
For instance, if you would like your applications to be able to add stuff to the application menu you could create the following interface:
class ApplicationMenu
{
// The "File" menu
IMenuItem File { get; }
}
interface IMenuRegistrar
{
void Register(ApplicationMenu menu);
}
Which means that your plugin can create the following class:
[Component]
public class CoolPluginMenuRegistrar : IMenuRegistrar
{
public void Register(ApplicationMenu menu)
{
menu.File.Add("mnuMyPluginMenuName", "Load jokes");
}
}
The [Component] attribute is used by my container so that it can discover and automatically register classes for you.
All you need to do to register all extension points like the one above is this:
public class Program
{
public static void Main(string[] args)
{
var registrar = new ContainerRegistrar();
registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll");
var container = registrar.Build();
// all extension points have been loaded. To load all menu extensions simply do something like:
var menu = GetMainMenu();
foreach (var registrar in container.ResolveAll<IMenuRegistrar>())
{
registrar.Register(menu);
}
}
}
These extensions would be "hooked" into different areas of the application, such as aded as event handlers of certain classes. From my knowledge, IoC containers allow dynamically discovering objects at runtime and registering them in a container.
Yep. You get all of that.
Is an IoC container able to also do this hooking into various events for me? Or is this task easier to do without such a framework?
Yes. I got a built in event mechanism. Put the event classes (regular .NET classes in shared class librararies). The simply subscribe on them by implementing an interface:
[Component]
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted>
{
ISmtpClient _client;
IUserQueries _userQueries;
public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
{
_client = client;
_userQueries = userQueries;
}
public void Invoke(ReplyPosted e)
{
var user = _userQueries.Get(e.PosterId);
_client.Send(new MailMessage(user.Email, "bla bla"));
}
}
And to publish events:
DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject"));
The events can be handled by any plugin as long as they:
Can access the event class
Have been registered in the container ([Component] or manual registration)
Implements ISubscriberOf<T>
Is it common that the plugin itself offer a Register method to do the registration?
Yep. Through different interfaces which are defines as extension points in a shared assembly.
Should the IoC do the registration? (how is that usually done?)
Yes. If the container provides it.
How can extension points be easily defined when using an IoC container ?
You can read about it in more detail here: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
I am working on developing a plug and play framework in ASP.Net MVC whereby I can define modules as separate projects from the Main project. So, a developer can create as many modules as they want.
What I need is that to be able to update settings of any of such modules. For that, in the main project, I defined a base class for some common settings plus each module has its own custom settings. When there is any edit on a module, I have to instantiate instance of that module in the main project. But, main project has no knowledge of any modules.
How do I achieve this?
Thanks!
You can use dependency injection and inject those modules to your application at composition root. As per configuration you can use code or xml (configuration file). You can do auto wiring, late binding etc depending on what you really need.
You can also have initializers at each module so whenever you register a module, it should initialize your registered modules and inject dependencies etc.
Depending on your need, you would have to create a solution that relies on interfaces.
Essentially, the application exposes an API dll with an interface called IModule. IModule has one method called Run(). Your main application will load up the module's assembly, look for something that implements IModule, makes one of those objects and calls Run() on it.
Here is an old article describing how to host a sandbox to run modules inside.
http://msdn.microsoft.com/en-us/magazine/cc163701.aspx
namespace MyApplication.Api
{
public interface IModule
{
void Run();
}
}
The developer would create something like this
public class MyObject : MarshalByRefObject, IModule
{
public void Run()
{
// do something here
}
}
The application will load it up with some kind of Reflection.
public void LoadModule()
{
var asm = System.Reflection.Assembly.Load(/* Get the developer module name from somewhere*/);
var types = asm.GetExportedTypes();
foreach(var t in types)
{
foreach(var i = t.GetInterfaces())
{
if(i == typeof(IModule))
{
var iModule = System.Activator.CreateInstance(t);
iModule.Run();
}
}
}
}
It would be best if you run the code in another appDomain, but it adds a lot of complexity.
public void LoadModuleInAppDomain()
{
// Spin up a new AppDomain
// Load the assembly into the app domain
// Get the object
// Call the Run Method
}
I'm trying to inject specific class into my WCF service but it doesn't work and I can't understand why. I'm VERY NEW to MEF and patterns, just trying to make it work. Watched series of videos to understand what it is about but bootstraping won't work in my case since it is not Silverlight
http://channel9.msdn.com/blogs/mtaulty/mef--silverlight-4-beta-part-1-introduction
Here is my Web application's Global.asax code. This is non MVC, just regular ASP.NET app:
private void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
var catalog = new WebScopedCatalog(new DirectoryCatalog(Server.MapPath("~\\bin")));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
FIRST, I'm not sure I even bootrstrap it properly.. SECOND, I'm using http://www.timjroberts.com/2011/02/web-scoped-mef-parts/ as a guidance for web-scoped parts. I need that because some injected objects supposed to live during request only.
Now, I have following class:
[Export(typeof(ITest))]
[WebPartCreationPolicy(WebCreationPolicy.Session)]
public class Test : ITest
{
public string TestMe()
{
return "Hello!";
}
}
And my service looks like:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MobileService
{
[Import]
public ITest MyTestClass { get; set; }
public MobileService()
{
int i = 10;
}
When breakpoint hits at i=10 - I have NULL inside MyTestClass. Clearly, MEF does not initialize this class for me. Am I missing something?
EDIT:
When I examine catalog - I see my class Exported but I don't see it imported anywhere...
EDIT 2:
Daniel, Thank you. It makes sense. It still feels litle like a magic for me at this point. Yes, WCF creates this service. Than I have MembershipProvider and various Utility classes that ALL need the same import. And I'm not creating neither of those classes so I can't have Mef creating them. (Service created by WCF, MembershipProvider created by who-knows-what, Utility classes have static methods..) I wanted to use Mef instead of storing my stuff in HttpContext.Current. My container object doesn't have SatisfyImports. It has SatisfyImportsOnce. What if I do it in many different constructors? Will Mef share same singleton or it will be creating new instance every time?
At this point I wonder if I should even use Mef in this particular scenario..
MEF won't satisfy imports for objects it doesn't create. What is it that creates MobileService? If it's not MEF, then the import won't be satisfied by default. Even if it is MEF, the import wouldn't be satisfied in the constructor- you can't set properties on an object you create until it is done being created (ie the constructor has finished).
You can call container.SatisfyImportsOnce(mobileService) to satisfy the imports of a part. You should try to avoid doing this everywhere you need a MEF import. If you can, you should export a part and import it from another part so that MEF handles the creation for you. However, it looks like this part may be created by WCF so you can't have MEF create it, and in that case it would be OK to use SatisfyImportsOnce.
Response to EDIT2: If you use the same container each time, MEF will by default only create one instance of the part with the export. You can set the CreationPolicy to NonShared (in either the export or import attribute) to change this.
As for whether it makes sense to use MEF the way you are trying to, I don't know enough about writing web services to give you any advice on that.
The web-scoped part creation policy that I wrote won't help with WCF services.
I've posted a new blog post that documents an approach to composeable WCF services:
http://www.timjroberts.com/2011/08/wcf-services-with-mef/
Basically, you need to implement a custom Instance Provider that is MEF-aware and can compose the WCF service object when it is created.
I wrote about how to compose your WCF in a generic way that its configuration based here:
Unit Testing, WCF and MEF
I actually built my solution on the code samples Tim Robert's provided in his post. only that I took it a bit further and instead of using code in the global asax i moved the configuration into the web.config so its easier to maintain.