I'm having a conundrum here, and I'm not even sure it's possible.
I'm developing a pluginbased application, where all the plugins will have access (read/write) to a shared configuration on the host application. There are easier ways of achieving the problem I'm presenting, but since this is a non-work related project, I'm free to play around :)
Let's say we have Plugin_A that is inheriting a PluginBase abstract class. The abstract class exposes a IConfiguration Config property that can be accessed by the plugin to write to this shared configuration. The IConfiguration Config is set properly by the host upon loading the plugin, to limit the available configuration that particular plugin will access.
What I would like to do is try and use the Dynamic keyword in C# 4.0 to seamlessly write the config-class.
in pseudo C# code here's what I would like to achieve
public class Plugin_A: PluginBase
{
public void DoSomethingWithConfig()
{
ShowAMessageBox(Config.SomeMessage);
Config.HasShownMessage = true;
}
}
Now - in this example I don't want to actually define the .SomeMessage and .HasShownMessage but rather have them be dynamic and returned when called upon.
It seems like a stretch, but is this at all possible?
I don't think you want to implement the IDynamicObject interface, I recommend you have Config inherit from DynamicObject instead. You'll want to override TryGetMember and TrySetMember at least for your example. TryInvokeMember will be necessary if you want to dynamically call methods. Implementing the whole interface is much more difficult.
So, your config class(es) will need to inherit DynamicObject and implement IConfiguration. You can then either declare the field as a dynamic item or as IConfiguration objects and cast them dynamic before you want to use their dynamic behaviors.
Related
I did my best with the title. What I am trying to accomplish is tiered modularity with dependency injection. Whether or not this design pattern is good is a question for another forum.
Because I am using dependency injection, I have interface/implementation pairs. This is the top-level inteface:
public interface IConfiguration<T> where T : ConfigData
{
T GetConfig();
}
Where ConfigData is a simple class that exposes get/set properties like LogLevel and Environment.
There is a base implementation of the interface:
public abstract class ConfigurationBase<T> : IConfiguration
{
protected ConfigData Config { get; set; }
public T GetConfig()
{
return Config as T;
}
}
Now for the dependency injection part of this! I have several interface/implementation pairs that hierarchically inherit from one another. Furthermore, their protected Config property also exposes more properties in each subsequent child class. Here are my interface/implementation signatures:
public interface IGeneralConfiguration : IConfiguration<GeneralConfigData>
public class GeneralConfiguration : ConfigurationBase<GeneralConfigData>, IGeneralConfiguration
public interface ILoginConfiguration : IConfiguration<LoginConfigData>, IGeneralConfiguration
public class LoginConfiguration : ConfigurationBase<LoginConfigData>, ILoginConfiguration
public interface IAppConfiguration : IConfiguration<AppConfigData>, ILoginConfiguration
public class AppConfiguration : ConfigurationBase<AppConfigData>, IAppConfiguration
Note that the inheritance scheme for the config data element is ConfigData → GeneralConfigData → LoginConfigData → AppConfigData. The config data element just exposes more properties specific to login/the application etc. (like Username or StartUri) in each child.
Now, I can use this configuration concept across all my modules. As far as dependency injection goes, resolving IGeneralConfiguration, ILoginConfiguration or IAppConfiguration will yield the exact same instance. However, now general modules only need to resolve IGeneralConfiguration, modules specific to login will only need to resolve ILoginConfiguration, and app-specific modules can resolve IAppConfiugration, all so that they can access parts of their config data specific to the concern they are trying to handle. This modularity allows me to create smaller side-apps that reuse modules from the main application without having to do a lot of custom coding (for example, I can reuse the login module without the need for referencing app-specific modules) as long as I slightly alter my dependency registration.
If you are still with me up to this point, the only problem with this model is that in all of my sub classes (that inherit from ConfigurationBase<T>), they all need the ConfigData() implementation from the interface above them. This means that class LoginConfiguration needs a method definition for public GeneralConfigData GetConfig(), and class AppConfiguration needs a method defintion for both public GeneralConfigData GetConfig() as well as LoginConfigData GetConfig().
So fine. I do that. Now, in my application-specific modules, I get a compiler error. Up in my class field definitions, I have private IAppConfiguration _appConfiguration;. Later in a method, I make a reference to it:
var element = _appConfiguration.GetConfig().AppSpecificConfigElement;
The compiler is confused, saying
the call is ambiguous between the following or properties 'IConfiguration.GetConfig()' and 'IConfiguration.GetConfig()'
Why doesn't the compiler see that the type is IAppConfiguration and define the call to GetConfig() to the AppConfiguration's GetConfig() (where T is defined as AppConfigData)?
Is there an obvious way to disambiguate the call to GetConfig() using my scheme?
If I understand correctly then what you just did is that you have two methods that have same signature except for the return value which cannot be resolved automatically. Compiler doesn't (and cannot) traverse all subclasses derived from ConfigData to determine that AppSpecificConfigElement belongs to AppConfiguration and pick overload based on that - even if it did you can have multiple classes that have AppSpecificConfigElement property so it won't be much wiser. You need to help compiler understand what you need, either by typing _appConfiguration to proper type or using typed descendant of ConfigData instead of var in your statement first and then get property.
In both cases I think you seriously over-engineered and I would suggest to step back and reconsider your approach. As #zaitsman said these objects should be POCOs and have different loader (DB, filesystem, ...) implementing simple Load/Save interface that can be then passed to DI based on context.
Given a plugin that implements IPlugin:
interface IPlugin
{
void DoWork();
void Configure(object config);
}
The host application will load up the plugin, and then find its configuration class at run time and pass it to the plugin's Configure method.
How can I make Configure take a strongly-typed class instead of type object? Are generics the answer here? Marking up classes with attributes? The plugins will be loaded via MEF, in case that's a consideration. Please help me pose this question in a more objective way if this seems like polling.
Based on question and comments made it sounds like you are looking for this:
Create a plugin that is unknown other than it implements IPluglin. Once found, create an unknown Configuration object and pass it in to get the plugin configured.
How would you know what type of Configuration object to create? You could get around the interface limitation of object and use a generic TConfiguration, but that doesn't really help because there is no way to know what the correct type the author wanted for their configuration.
I would actually follow jaywayco's advice and set up an IConfiguration interface with common members you need at the core.
The change I would make to this advice is adding an extra method to your interface called CreateNewConfig (or whatever you like) that returns you a new instance of the type of config the author wanted. No matter what it should implement the new configuration interface.
public interface IPlugin
{
public IConfiguration CreateNewConfig();
public void Configure(IConfiguration config);
}
void Test()
{
IPlugin myPlugin = PluginFactory.CreateSomePlugin();
IConfiguration pluginConfig = myPlugin.CreateNewConfig();
InitializeConfigWithCoreSettings(pluginConfig);
myPlugin.Configure(pluginConfig);
}
The only other way to know exactly what config type the plugin wanted is to force them to declare the type in a property, but you can get that same information just by calling CreateNewConfig().GetType().
There is a problem I see and that is you are allowing the plugin to configure itself. If this is the case, why are you needing to pass in an object? Surely the plugin can find a way to store its own configuration and read it. Unless you are serializing and deserializing the config the plugin used previously, I don't see the point in even needing to pass in a config other than for common properties you want them to have. If it really is core stuff, then definitely use an interface or your own concrete class.
You can't and probably don't want to.
If you changed the signature of Configure to accept a strongly typed configuration object, you are limiting how other plugins can be configured.
Probably what you want, is another interface that provides a contract for the minimum configuration proprties that a plugin will need
So:
interface IPlugin
{
void DoWork();
void Configure(IConfigurationData config);
}
In my option makes more sense and your plugin, which has internal awareness of how it needs to be configured can attempt to cast IConfigurationData to something more verbose.
To satisfy the generics approach I would do something like this:
interface IPlugin
{
void DoWork();
void Configure<TConfig>(TConfig config) where TConfig : IConfigurationData;
}
The generics approach is probably syntactically nicer but they are essentially equivalent
I've built a reusable Class Library to encapsulate my Authentication logic. I want to be able to reuse the compiled *.dll across multiple projects.
What I've got works. But, something about how I'm making the reference, or how my Class Library is structured isn't quite right. And I need your help to figure out what I'm doing-wrong/not-understanding...
I've got a Class Library (Authentication.dll) which is structured like this:
namespace AUTHENTICATION
{
public static class authentication
{
public static Boolean Authenticate(long UserID, long AppID) {...}
//...More Static Methods...//
}
}
In my dependent project I've added a reference to Authentication.dll, and I've added a using directive...
using AUTHENTICATION;
With this structure I can call my Authenticate method, from my dependent project, like so...
authentication.Authenticate(1,1)
I'd like to be able to not have to include that "authentication." before all calls to methods from this Class Library. Is that possible? If so, what changes do I need to make to my Class Library, or how I'm implementing it in my dependent project?
In C# a function cannot exist without a class. So you always need to define something for it, being a class for a static method or an object for an object method.
The only option to achieve that would be to declare a base class in the Authentication assembly from which you inherit in the dependent projects.
You could expose Authenticate as a protected method (or public works too), and call it without specifying the class name.
public class MyClassInDependentProject : authentication
{
public void DoSomething(int userId, long appId)
{
var success = Authenticate(userId, appId);
…
}
}
That said, you'll quickly find this to be a bad design. It conflates a cross-cutting concern with all sorts of other classes, and those classes are now precluded from inheriting from any other class.
Composition is a core principle of object-oriented programming, and we have the idiom "Favor composition over inheritance." This simply means that we break down complexity into manageable chunks (classes, which become instantiated as objects), and then compose those objects together to handle complex processing. So, you have encapsulated some aspect of authentication in your class, and you provide that to other classes compositionally so they can use it for authentication. Thinking about it as an object with which you can do something helps, conceptually.
As an analogy, think about needing to drill a hole in the top of your desk. You bring a drill (object) into your office (class). At that point, it wouldn't make sense to simply say "On," because "On" could be handled by your fan, your lamp, your PC, etc. (other objects in your class). You need to specify, "Drill On."
If you are making a class library in C# you should learn to use the naming conventions that exists: Design Guidelines for Developing Class Libraries
Here is how you should name namespaces: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/interface
C# is also an object oriented language, hence the need of classes (using Authentication as you should name your class).
It also seems like the data source is hard coded. Your class library users (even if it's just you) might want to configure the data source.
Google about singleton and why it's considered to be an anti pattern today (in most cases).
You are obliged to use Class in order to invoke your method, just
When is static class just NameClass.Method
When is not static, you must create instance, ClassName ob = new ClassName(); ob.Method();
The format of a call like this is class.method, and you really can't escape using the "class" moniker even with the "using" designation. Something has to "host" the function.
I don't think what you are asking for is possible without using the base class method Jay mentioned. If all you want is to simplify the syntax whenever you call Authenticate() however, this silly solution (adding an extra method in each class that needs to do authentication) may be just what you want:
private static void DoAuth(long UserID, long AppID){
authentication.Authenticate(UserID, AppID)
}
If the ID's are always the same within some context, you could also overload it:
private static void DoAuth(){
DoAuth(1,1)
}
Yes, this does mean you have to add more code wherever you want to do the authentication (that's why it's silly! ;) ). It does also however, also reduce this:
authentication.Authenticate(1,1);
...into this:
DoAuth();
I leave the cost / benefit analysis of this up to you..
I know I am some 3 years late but here goes nothing.
To keep your code cleaner and more readable you should create a new namespace for all the re-usable code that you want to have. Then in that namespace have the Authentication Class and Authenticate Function.
To use this you can easily set a using on your namespace and use the function as you are doing like
Authentication.Authenticate()
But to use
Authenticate()
by itself you can always do
using MyNamespace.Authentication;
and in your code use Authenticate Function directly.
I'm working on some framework-ish code designed to execute a huge number of operations (hundreds of thousands), all of which use the same basic components, but need to accept operation-specific configuration data from an external source.
Assume for the moment that there's a configuration repository which, given the appropriate list of setting names, knows how to load these settings efficiently and store them in a type like the following:
public interface IConfiguration
{
dynamic Get(string key);
void Set(string key, dynamic value);
}
What I'm planning to do is implement either some fluent mapping syntax or just decorate the component classes with attributes like so:
public class MyComponent : IActivity
{
[Configuration("Threshold")]
public virtual int Threshold { get; set; }
[Configuration("SomeKey", Persistence = ConfigPersistence.Save)]
public virtual string SomeSetting { get; set; }
}
You get the picture... hopefully. What's important to note is that some properties actually need to be saved back to the repository, so conventional DI libraries don't work here; and even if they did, they're blunt instruments not designed to be spinning up hundreds of thousands of components and loading/saving millions of attributes. In other words, I don't think I'm reinventing the wheel, but if somebody wants to try to convince me otherwise, feel free.
Anyway, I'm considering two possible options to handle the "injection" of configuration data into these component instances:
Plain vanilla Reflection - scan the type for configuration attributes and save the member info (along with the config key) in a static dictionary. Then use reflection methods such as PropertyInfo.SetValue and PropertyInfo.GetValue for the injection and extraction (for lack of a better term). This is similar to the approach used by most DI libraries.
Use a dynamic proxy such as Castle and hook up an interceptor to the decorated properties, such that instead of referencing private/autogenerated fields, they reference the IConfiguration instance (i.e. the get method calls IConfiguration.Get and the set method calls IConfiguration.Set). This is similar to the approach used by NHibernate and other ORMs.
The full implementation may end up being a fair amount of work, so I don't want to go too far down the wrong path before realizing I missed something.
So my question is, what are the pros/cons of either approach, and what are the pitfalls I need to avoid? I'm thinking in broad terms of performance, maintainability, idiot-proofing, etc.
Or, alternatively, are there other, quicker paths to this goal, preferably which don't have steep learning curves?
Dynamic proxy is much better approach. Define a "configuration" interceptor that injects the value from the configuration into your component (preferably lazily). Using Dynamic proxy, I'd also implement a generic IDisposable interface to your proxied Component, so that when the object is disposed or GC'd, it will persist configuration values based on the Peristence flag set in your attribute.
In one of the applications I am working on, there are two basic functionalities included: Create and Update.
However, there is a need sometimes to add custom code, so I thought of extending the code by allowing 3rd parties to write and embed their own code:
OnCreating
OnCreated
OnUpdating
OnUpdated
Is there a way to enable the above across multiple assemblies? MEF might help here?
Thank you
Regards
Thanks all for your replies.
Having such an interface means each external assembly has to implement that interface as needed. Then, my application's code, needs to loop through the currently running assemblies, detect all classes implementing that interface, and run their methods?
Does MEF fit here? I can export the implementation from external assemblies and import them inside my app?
Thank you
Regards
You can't have partical classes accross assemblies because partial classes are a language feature, and not a CLR feature. The C# compiler merges all the partial classes into one real class, and that single class the the only thing left after compilation.
You have a couple of alternatives:
Offer events
Make the methods virtual and override them
Use an interface
Your problem looks like it fits events best. The user can simply subscribe to them in the other assembly.
Regarding your MEF question, you could probably do something like the following to run methods from an interface:
var catalog = new DirectoryCatalog("bin");
var container = new CompositionContainer(catalog);
container.ComposeParts();
var plugins = container.GetExportedValues<IPlugin>();
foreach (IPlugin plugin in plugins)
{
plugin.OnCreating();
}
Or create an interface with events as Brian Mains suggested:
public interface IPlugin
{
event OnCreatingEventHandler OnCreating;
}
then the above code would be more like:
var catalog = new DirectoryCatalog("bin");
var container = new CompositionContainer(catalog);
container.ComposeParts();
var plugins = container.GetExportedValues<IPlugin>();
foreach (IPlugin plugin in plugins)
{
plugin.OnCreating += MyOnCreatingHandler;
}
I think I like the latter for the method names you specified. For my plugin work, I've created an interface similar to the following:
public interface IPlugin
{
void Setup();
void RegisterEntities();
void SeedFactoryData();
}
The RegisterEntities() method extends the database schema at runtime, and the SeedFactoryData() method adds any default data (eg. adding default user, pre-population of Cities table, etc.).
Having partial classes supported across assemblies isn't supported.
The reason being that all partial class definitions are combined into a single class during compile time. That single class resides in a single assembly.
Consider using an interface:
IUpdatableObject<X>
Creating(X obj);
Created(X obj);
Updating(X obj);
Updated(X obj);
And then use this interface to add in custom code; each third party can implement this interface (well either they or you can through a wrapper) and this can be a tie into adding custom business logic.
HTH.
You (or the user) can use extension methods:
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Partial methods and classes must be in the same assembly. Partial methods are compiled out if not used. If you need extension points for you classes you should look into virtual methods or events.
Partial classes across assemblies aren't supported because the concept behind the partial class is to allow multiple developers to contribute different methods and members for the same class under a particular namespace.
This was done in order to help developers to sync the code into a single class, inside one assembly, build after compilation.