This question might be design related or code related, but I'm stuck so I'm open to any kind of answer; a pointer in the right way!
I have used MEF (Managed Extensibility Framework) to develop a piece of WPF software that will act as a form of orchestrator for plugins. The application is simply redirecting data between the plugins as of the users choice, so what the plugin does is not known at all (especially since they can be developed by 3rd party devs).
The application and the plugin are sharing an interface as a way of knowing what methods to call for, so the traffic goes both ways: a plugin calls a method in the main application sending it data and the main application is passing this data to another plugin.
This works so far, but I'm having a problem with synchronous behavior. All methods defined by the interface lack a return value (Void) and I'm struggling to get a "fire and forget" kind of approach where the calling application does NOT need to sit around waiting for the plugins receiving function to finish execute code (and calls that goes back to the main app!).
So whats the best approach to solving this? Letting every plugin (and the main app) put it's workload on a "stack" of some kind just to be able to return the control to the calling side and then have some mechanism that runs separately that works through the stack item by item (and do this stacking approach as async?)?
Other things worth noting is that the plugins are running in separate threads (according to the debugger thread window) and when they are initialized they get a reference from the calling main application so they can fire functions in the main app. The plugins also very often need to tell the main app what status they are in (idle, working, error etc) and also send data to be logged by the main app, so this very often creates a nested call hierarchy (if you follow me, hard to explain).
I'm using .Net 4.5 for this one.
Below is some simplified example of the code. I replaced some names, so if there is a spelling error somewhere, its just here and not in the real code. :)
The interface:
public interface IMyPluggableApp
{
void PluginStatus(string PluginInstanceGuid, PluginInstanceState PluginInstanceState);
void DataReceiver(string PluginInstanceGuid, string ConnectorGuid, object Data);
void Logg(string PluginInstanceGuid, LoggMessageType MessageType, string Message);
}
public interface IPluginExport
{
PluginInfo PluginInfo { get; set; }
void Initialize(string PluginInstanceGuid, Dictionary<string, string> PluginUserSettings, IMyPluggableApp MyPluggableApp);
void Start(string PluginInstanceGuid, List<ConnectorInstanceInfo> ConnectedOutputs);
void Stop(string PluginInstanceGuid);
void PluginClick(string PluginInstanceGuid);
void PlugginTrigger(string ConnectorGuid, object Data);
}
The plugin:
public static IMyPluggableApp _MyPluggableApp
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IPluginExport))]
public class PluginExport : IPluginExport
{
public void Initialize(string PluginInstanceGuid, Dictionary<string, string> pluginUserSettings, IMyPluggableApp refMyPluggableApp)
{
_MyPluggableApp = refMyPluggableApp; // Populate global object with a ref to the calling application
// some code for setting saved user preferences
_MyPluggableApp.PluginStatus(PluginInfo.PluginInstanceGuid, PluginInstanceState.Initialized); // Tell main app we're initialized
}
public void Start(string PluginInstanceGuid, List<ConnectorInstanceInfo> ConnectedOutputs)
{
// Some code for preparing the plugin functionality
_MyPluggableApp.PluginStatus(PluginInfo.PluginInstanceGuid, PluginInstanceState.Initialized); // Tell main app we started
}
public void PlugginTrigger(string ConnectorGuid, object Data)
{
_MyPluggableApp.PluginStatus(AvailablePlugins.PluginInfo.PluginInstanceGuid, PluginInstanceState.Running_Busy); // Tell main app we're busy
// Run the code that actually provides the functionality of this plugin
_MyPluggableApp.PluginStatus(AvailablePlugins.PluginInfo.PluginInstanceGuid, PluginInstanceState.Running_Idle); // Tell main app we're idle
}
// and so on ...
}
And the main application:
public partial class MainWindow : IMyPluggableApp
{
[ImportMany(typeof(IPluginExport))]
IPluginExport[] _availablePlugins;
public void PluginStatus(string PluginInstanceGuid, PluginInstanceState PluginInstanceState)
{
// Code for setting status in GUI
}
public void DataReceiver(string PluginInstanceGuid, string ConnectorGuid, object Data)
{
ConnectorInfo connector_source = GetConnectorInfo(ConnectorGuid);
PluginInfo plugin_source = GetPluginInfo_ByPluginInstanceGuid(PluginInstanceGuid);
ConnectorInstanceInfo connector_destination = (from i in _project.PluginInstances
from y in i.ConnectedConnectors
where i.PluginInstanceGuid == PluginInstanceGuid
&& y.ConnectedFromOutput_ConnectorGuid == ConnectorGuid
select y).FirstOrDefault();
_availablePlugins.Where(xx => xx.PluginInfo.PluginInstanceGuid == connector_destination.ConnectedToInput_PluginInstanceGuid).First().PlugginTrigger(ConnectorGuid, Data);
}
public void Logg(string PluginInstanceGuid, LoggMessageType MessageType, string Message)
{
// Logg stuff
}
}
It's the DataReceiver function in the main app thats receives the data, looks what plugin should have it, and then sends it (via PlugginTrigger function).
A couple of observations:
Fire and forget is a requirement of the host so not something the plug-in implementations should have to worry about.
I don't think (please correct me if I am wrong) the CLR supports calling methods in a "fire-and-forget"-ful way within the same AppDomain. If your plug-ins were loaded in to separate processes, and you were communicating with them using WCF then you could simply set the IsOneWay property on your OperationContractAttribute.
The second point suggests one solution, which seems slight overkill for your situation - but let us mention it anyway. Your plug-ins could host in-process WCF services, and all the communication between the WPF application and the plug-ins could be done through the WCF service proxies. However, this comes with a configuration nightmare and is really opening a can of worms to a whole bunch of other issues you would have to solve.
Let us start with a simple example of the initial problem, and attempt to solve it from there. Here is the code for Console application with a plug-in:
public class Program
{
private static void Main(string[] args)
{
var host = new CompositionHost();
new CompositionContainer(new AssemblyCatalog(typeof(Plugin).Assembly)).ComposeParts(host);
var plugin = host.Plugin;
plugin.Method();
Console.ReadLine();
}
private class CompositionHost: IPartImportsSatisfiedNotification
{
[Import(typeof (IPlugin))] private IPlugin _plugin;
public IPlugin Plugin { get; private set; }
public void OnImportsSatisfied()
{
Plugin = _plugin;
}
}
}
public interface IPlugin
{
void Method();
}
[Export(typeof(IPlugin))]
public class Plugin : IPlugin
{
public void Method()
{
//Method Blocks
Thread.Sleep(5000);
}
}
The problem is the call to plugin.Method() is blocking. To solve this, we change the interface that is exposed to the Console application to the following:
public interface IAsyncPlugin
{
Task Method();
}
A call to an implementation of this interface will not block. The only thing we need to change is the CompositionHost class:
private class CompositionHost: IPartImportsSatisfiedNotification
{
[Import(typeof (IPlugin))] private IPlugin _plugin;
public IAsyncPlugin Plugin { get; private set; }
public void OnImportsSatisfied()
{
Plugin = new AsyncPlugin(_plugin);
}
private sealed class AsyncPlugin : IAsyncPlugin
{
private readonly IPlugin _plugin;
public AsyncPlugin(IPlugin plugin)
{
_plugin = plugin;
}
public Task Method()
{
return Task.Factory.StartNew(() => _plugin.Method());
}
}
}
}
Obviously this is a very simple example, and the implementation may have to vary slightly when applying it to your WPF scenario - but the general concept should still work.
Related
I have a somewhat basic design question that I have not been able to find a good answer to (here, on other forums nor the books I've consulted)
I'm creating a dll and is wondering what the best way to expose its content would be. I'm aiming for a single point of entry for the apps using the dll.
The solution should adhere to the Dependency Inversion Principle (DIP) which would imply the use of an interface. But here is the kicker: the functionality of the dll requires an object to be instantiated and there must only be almost one instance at any time (kinda like a singleton though the thought sends shivers down my spine) It is this fact that I would like to spare the users of the DLL from knowing about.
Some code to explain what I would like to be able to do:
The dll:
namespace MyQuestionableDll
{
interface IMyQuestionableDll
{
public static IMyQuestionableDll Instance; // This is not allowed which makes sense
public void PressTheRedButton();
}
internal class QuestionableImplementation : IMyQuestionableDll
{
public void PressTheRedButton()
{
// Distribute Norwegian Black Metal at local school
}
}
}
And the use case:
using MyQuestionableDll;
class UnluckyAppThatIsForcedToUseQuestionableDlls
{
static void Main(string[] args)
{
IMyQuestionableDll questionableInstance = IMyQuestionableDll.Instance; // Again not allowed which still makes sense
questionableInstance.PressTheRedButton();
// or simply
MyQuestionableDll.Instance.PressTheRedButton();
}
}
An abstract class could be part of the answer but it then starts to feel like not following the DIP anymore.
Any great design insights, knowledge of best practices when making dlls or recommendations regarding Norwegian Black Metal?
If the explanation is too vague I will gladly elaborate on it.
Cheers!
- Jakob
I could imagine a two-factor approach:
A factory interface (that will create/return an instance of ...)
The API interface
For Example:
public interface IMyApiFactory
{
IMyAPI GetInstance();
}
public interface IMyAPI
{
// Whatever your API provides
}
This way you have the complete control inside your dll about how to create and reuse instances (or not).
A similar way would be some kind of Builder-Pattern:
public interface IMyApiBuilder
{
IMyApi Build();
}
public interface IMyApi
{
void PressTheRedButton();
// Whatever it does else
}
public sealed class MyAPI : IMyApi, IMyApiBuilder
{
public static IMyApiBuilder Builder = new MyAPI();
private MyAPI()
{
// CTOR ...
}
// vv Notice _explicit_ interface implemenations.
// https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation
IMyApi IMyApiBuilder.Build() { return this; }
void IMyApi.PressTheRedButton()
{
// ...
}
}
// USAGE:
IMyApi api = MyAPI.Builder.Build();
Thank you so much Fildor and ema! The ideas of adding a factory method, a factor interface or even a full-blown builder is definitely good solutions! And it got me thinking about how to incorporate them into my DLL while still sparing its users. They don't need to know that it in fact is a foul smelling factory with polluting smokestack emissions that are creating the instance :)
Then I came across Default Interface Methods and the structure of my approach ended up being
public interface MyQuestionableDll
{
static readonly MyQuestionableDll Instance = new QuestionableImplementation();
void PressTheRedButtonBelowTheDoNotPushSign();
}
internal class QuestionableImplementation : MyQuestionableDll
{
public void PressTheRedButtonBelowTheDoNotPushSign()
{
// Distribute German Volksmusik at local school
}
}
// and the use case
var questionableInstance = MyQuestionableDll.Instance;
questionableInstance.PressTheRedButtonBelowTheDoNotPushSign();
Thanks again Fildor and ema!
- Jakob
Consider the following type:
class SomeType
{
public void Configure()
{
var windowsService = new ServiceController("msdtc");
windowsService.Start();
}
}
There are at least three issues.
We have implicit dependency to ServiceController.
We cannot to unit test Configure().
We have a new operator that breaks our DI strategy.
So to fix it we can extract another type and input it to our SomeType.
interface IWindowsService
{
void Start();
}
class WindowsService : IWindowsService
{
private readonly ServiceController _serviceController;
public WindowsService(string serviceName)
{
_serviceController = new ServiceController(serviceName));
}
public void Start() => _serviceController.Start();
}
class SomeType
{
private readonly IWindowsService _msdtcService;
public SomeType(Func<string, IWindowsService> createServiceCallback) //explicit dependency
{
_msdtcService = createServiceCallback.Invoke("msdtc");
}
public void Configure() => _msdtcService.Start();
}
It fixes the issues #1 and #2 but we still have a new operator in the new type WindowsService. I try to understand should I register standart ServiceController in the DI-container or use it directly as demonstrated above (by new)?
container.RegisterType<ServiceController>();
Also I am not sure whether we should try to test WindowsService or maybe it would be better to rewrite it something like this:
class WindowsService : ServiceController, IWindowsService
{
}
Since WindowsService is now just inheriting we cannot test anything here. The type is already tested by Microsoft.
However it breaks incapsulation and maybe ISP from SOLID. Because we can cast IWindowsService to WindowsService or even to ServiceController.
What is the best way to deal with standart stable types?
Please refer me to another question if we have.
Thanks in advance.
interface ISomeInterface
{
void Configure();
}
class SomeType : ISomeInterface
{
public void Configure()
{
var windowsService = new ServiceController("msdtc");
windowsService.Start();
}
}
I would do it like above. Now nothing should directly depend on SomeType. Everything should depend on ISomeInterface. That keeps the dependency on ServiceController limited to a single class.
The new operator really isn't a problem. There's no IServiceController that ServiceController implements, so if you want to use it, you have to tie yourself to it. By hiding it in SomeType which does implement an interface, at least you've limited how many things have a direct dependency on it.
The problem you are dealing with is a subtype of a larger problem, the issue of dealing with system level calls in IoC.
Another example of the problem is the use of DateTime.Now. If you call this in your code, there is no way to isolate it away, which is a problem if you want to test in various time scenarios.
One solution is to abstractify away all system level calls, so that you can substitute your own mock operating system for the purpose of testing. Here is an example for DateTime. I'll provide an example for your specific issue too:
interface IOperatingSystem
{
void StartService(string name);
}
class OperatingSystem : IOperatingSystem
{
public virtual void StartService(string name) {
var windowsService = new ServiceController(name);
windowsService.Start();
}
}
class SomeType : ISomeType
{
private readonly IOperatingSystem _operatingSystem;
public SomeType(IOperatingSystem operatingSystem)
{
_operatingSystem = operatingSystem;
}
public void Configure()
{
_operatingSystem.StartService("msdtc");
}
}
In your IoC container:
container.RegisterType<IOperatingSystem, OperatingSystem>();
container.RegisterType<ISomeType, SomeType>();
Now you can isolate away all you want, just by overriding your operating system class:
class MockOperatingSystem : OperatingSystem
{
public override StartService(string name)
{
//Do something worthy of testing, e.g. return normally or throw an exception
}
}
and register (in your unit tests) like this:
container.RegisterType<IOperatingSystem, MockOperatingSystem>();
Now when you go to code this, you might choose to have different interfaces for different system functions (e.g. maybe you want a IServiceControlManager that is separate from other O/S calls). That is fine, and common. I prefer one big class for all my O/S calls, because I know those O/S calls are not going to change. Well, they might change, but if they do, I have much bigger problems, and rework will be unavoidable anyway.
I am writing a program that synchronizes playlists among different streaming services, the problem is every service uses different structures and functions.
I want to make it "modular" so i can add new services and syncronize them with the others without programming them for every service i have already in the application and the best idea i came out with is to implement it by using a sort of intermediate language (or intermediate models), e.g.
namespace Service1
{
class Service1Album
{
public string ID { get; set; }
public Service1Artist Artist { get; set; }
//Some other props...
public IntermediateAlbum ToIntermediate()
{
//conversion...
}
}
class Service1Artist
{
//Some props...
public string ID { get; set; }
public IntermediateArtist ToIntermediate()
{
//conversion...
}
}
}
namespace Intermediate
{
class IntermediateArtist
{
//Props that every service has in common...
}
class IntermediateAlbum
{
//Props that every service has in common...
}
}
In this way every service I implement accept as parameter for its functions Intermediate models and outputs his own models that can be converted.
Service1Album album = service1.GetAllAlbums()[0];
IntermediateAlbum intermediateAlbum = album.ToIntermediate();
service2.AddAlbum(intermediateAlbum);
service3.AddAlbum(intermediateAlbum);
Is there a way I can implement this more elegantly? And if so, is there a way I can inherit every service from something like a ServiceContainer that abstracts every service like this?
var sList = new List<ServiceContainer>{};
sList.Add(new Service1());
sList.Add(new Service2());
foreach (var service in sList)
{
service.addAlbum(new IntermediateAlbum()
{
//properties
});
}
Luca - Welcome! You're discovering the need for some design patterns in your code. That's really great - it means things are getting complex enough that you can start to lean on the patterns others have spent years refining in building your solution.
#1 - Switch to using Interfaces + Design Patterns
If I were you, I'd start by abstracting everything to interfaces (eg - you'd run your work in each Service against IAlbum's and IArtist's instead of concrete implementations).
Then, once your interfaces are in place, take a look at the .net code for the gang-of-four patterns to figure out how to layout the work.
#2 - The basics
There's a lot of code to write, but the skeleton might end up looking like this
namespace MusicService
{
public interface IAlbum {
//common album properties/methods
}
public interface IArtist {
//common artist properties/methods
}
internal abstract class AlbumBase:IAlbum {
// implement common functions and properties if you have them...
// otherwise, skip this
}
internal abstract class ArtistBase:IAlbum {
// implement common functions and properties if you have them...
// otherwise, skip this
}
}
namespace MusicService.AppleMusic
{
internal class Album:AlbumBase
{ //OR Album:IAlbum if you skipped that AlbumBase thing
//code apple music specific stuff here ...
// think of this as a "mask" that the apple album is
// wearing so that it can pretend to be an iAlbum
}
internal class Artist:ArtistBase
{
//same comments apply here
}
}
namespace MusicService.Spotify
{
internal class Album:AlbumBase
{
//GO and do liekwise with Spotify
}
internal class Artist:ArtistBase
{
//GO and do liekwise with Spotify
}
}
#3 - Implementing the actual SYNC
Now that you have the code you need for your various music services (neatly arranged, so your fellow programmers don't have to dig through your brain to figure out what you were thinking), you can code your SyncService.
I don't want to spoil the fun (sync service could use the decorator pattern or it could be a sort of composite -- not sure what your sync code needs to do), but your final sync code could be as easy as:
var myService = new SyncService();
myService.AddAppleMusic();
myService.AddSpotify();
myService.Sync();
Spoiling the Fun
OK. Fine. Here's what I'd do.
namespace MusicService {
public interface IService {
//propably a List<IAlbum> and List<IA> somewhere in here
void Sync();
}
public class SyncService {
internal List<IService> _services;
public void AddService(IService musicService) {
if(_services==null){_services=new List<IService>();}
_services.Add(musicService);
}
public void Sync() {
foreach(IService ms in _services) {
ms.Sync();
}
}
}
}
namespace MusicService.AppleMusic {
internal AppleSyncService:IService {
public AppleSyncService() {
//Do your apple-specific initializations here
}
public void Sync() {
//apple-sync
}
}
internal class ExtendService(){
public static void AddAppleMusic(this SyncService syncAgent) {
syncAgent.AddService(new AppleSyncService());
}
}
}
Obviously - none of that code compiles, and coding in notepad is probably a bad idea. But, it gives you a pattern-based alternative to your sample code above. AND - if you add a third music service, you don't run the risk of breaking apple and spotify just to wedge in that new one!
Good luck. Sounds like a fun project.
In the past I've built a MessageDispatcher component that scans an assembly for types decorated with certain attributes and initializes an instance of each. Then, when any object is fed to the MessageDispatcher instance, every previously initialized instance which contains a method which signature contains the type of the passed object has said method triggered with the specified parameter. For example, in a scenario like:
[Listener]
public class MyListener
{
MessageDispatcher _dispatcher; //Assigned elsewhere
[MessageListener]
public async Task DoSomething(int value)
{
var otherValue = await _dispatcher.Next<string>();
Console.WriteLine($"{value} is {otherValue}.");
}
}
The following code initializes an instance of the MyListener class, calls DoSomething and prints "7 is okay.":
var listener = new MessageDispatcher(typeof (ListenerAttribute));
listener.Dispatch(7);
listener.Dispatch("okay");
I would like to know if there are any libraries out there that are dedicated to or include a service like such. It has to be able to:
Scan assemblies and initialize types based on an attribute.
Dynamically "subscribe" to certain types
"Wait" on a value to be pumped from the dispatcher (like with the Next method in my example).
(as library recommendations is not allowed per the SO rules, here is an attempt to instead answer with an implementation)
You can get that with virtually any IoC. All they need is to be able to register services using an attribute or some other conventional way.
As for the message dispatching. Just create an interface like IMessageHandler<TMessage>. Implement it on all classes that should handle messages.
Example:
public interface IMessageHandler<TMessage>
{
void Handle(TMessage msg);
}
public class SomeService : IMessageHandler<UserCreated>
{
//[.. all other methods ..]
public void Handle(UserCreated msg)
{
// ...
}
}
To publish messages you create a dispatcher. Since you use a container you do not have to make it static. Use your container inside it (service location) to dispatch the messages. Now some peeps might say oohh no, service location is anti-pattern, buhuhuhu. Well no. Not in all cases. In this case it's an implementation details in a class with the specific purpose to identify and invoke other classes.
public interface IMessageDispatcher
{
void Dispatch<TMessage>(TMessage msg);
}
// The actual implementation differs
// depending on your choice of container.
public class ContainerBasedMessageDispatcher : IMessageDispatcher
{
Container _container;
public ContainerBasedMessageDispatcher(Container container)
{
_container = container;
}
public void Dispatch<TMessage>(TMessage message)
{
using (var scope = container.BeginLifetimeScope())
{
var handlers = scope.Resolve<IEnumerable<IMessageHandler<TMessage>>();
foreach (var handler in handlers)
{
handler.Handle(message);
}
}
}
}
The code is written directly in SO. So it might not work as-is. But hopefully it's given you an idea how to achieve what you want.
Usage:
public class UserService
{
IMessageDispatcher _dispatcher;
public UserService(IMessageDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public void Create(User user)
{
//[...]
_dispatcher.Dispatch(new UserCreated(user.Id));
}
}
this do however not dynamically allow you to subscribe on what you want. If just ignoring unwanted messages is not feasible. Then this answer is not for you.
I usually try to encapsulate my web service calls in my client side apps.
Rather than doing this:
public Guid FindUserIDSelected(string userName)
{
MyWebServiceReference service = new MyWebServiceReference(GetEndpointBasedOnEnv(Env));
return service.GetUserIDFromName(userName);
}
I have a static class that encapsulates the communication with the web services. It handles the endpoint resolution via determining the environment (and other such things).
So the above code changes to look like this:
public Guid FindUserIDSelected(string userName)
{
return Communication.GetUserIDFromName(userName);
}
But now I am having an issue. Silverlight only supports Asynchronous calls (at least as far as I am seeing). So calling a web service and then returning the value in an encapsulated call does not work.
The best I can come up with is passing in a delegate that is used in the Communication class for the completed event:
private Guid foundUserID;
public void FindUserIDSelected(string userName)
{
Communication.GetUserIDFromName(userName, GetUserIDCompleted);
}
private void QuestionRecieved(object sender, GetUserIDFromNameCompletedEventArgs e)
{
foundUserID= e.Result();
}
This has several problems (in my opinion).
I now have elements of the web services that have broken encapsulation (the completed call is really the web service return. I don't want the rest of my classes to have to care about the services).
I have had to expose my result (foundUserID) at the class level.
Am I being too rigid? Is that good enough? Is there a better way?
Am I the only one who has this issue?
In my opinion, it'd better to use eventing from your communication class, especially if you have some thing like [EventAggregator]1, so you can filter an event based on your specific argument
Below is the code snippet, this may be helpful for you.
public static class Communication
{
public static event EventHandler<MyEventArgs> ServiceCallComplete;
public static void InvokeMyAcionComplete(MyEventArgs e)
{
EventHandler<MyEventArgs> handler = ServiceCallComplete;
if (handler != null) handler(null, e);
}
public static void CallService ()
{
//Performed async call
// Fire the event to notify listeners
OnServiceCalled();
}
private static void OnServiceCalled ()
{
InvokeMyAcionComplete(new MyEventArgs());
}
}
public class ClientCode
{
public void CallService()
{
Communication.CallService();
//Subscribe to the event and get notified when the call is complete
Communication.ServiceCallComplete += OnServiceCalled;
}
private void OnServiceCalled(object sender, MyEventArgs e)
{
//MyEventArgs is your customized event argument
//Do something with the result
}
}
Hope this help