Using Net 4.5.1 and StructureMap 3.1.4
I have services that extending an abstract class:
public abstract class Charting<T> {
protected readonly String baseConfigurationString;
public Charting(String baseConfigurationString)
{
this.baseConfigurationString = baseConfigurationString;
}
...
}
For every concrete service I want to set the baseConfigurationString. Right now I am doing it individually per service:
public class MyRegistry : Registry
{
public MyRegistry()
{
Profile("Development", x => {
ForConcreteType<AveragePartySizeChart>().Configure.Ctor<String>("baseConfigurationString").Is(MyDbConfiguration.getBaseConnectionString());
...next service....about 6 total
});
}
}
Is there anyway to do this generally acting against the abstract class despite it having a generic qualifier?
My suggestion, and what we did with StructureMap for configuration within FubuMVC, is to create a class something like:
public class ConnectionSettings
{
public string Connection {get;set;}
}
and resolve that through StructureMap as a singleton. Then in any class that needs the connection string, just do:
public abstract class DatabaseConnectionUser
{
public DatabaseConnectionUser(ConnectionSettings settings){}
}
Autowiring will connect your ConnectionSettings object to all the class objects that take in
that object in their constructor function.
You could try using a custom IPluginGraphConfiguration class in StructureMap 3 to set the ctor argument explicitly on all Instance's that build a subclass, but I think that would be more work.
This does not solve your abstract constructor argument setting via Profile problem but I would like to suggest that you avoid taking dependencies on primitive types like System.String and use an abstraction instead.
You could have an type IDatabaseSettings which gets the connection settings you desire for either environment variables or application settings.
public interface IDatabaseSettings
{
string DbConnectionString { get; set; }
}
public class DatabaseSettings : IDatabaseSettings
{
public string DbConnectionString { get; set; }
}
public class DatabaseRegistry : Registry
{
public DatabaseRegistry()
{
For<IDatabaseSettings>().Use(c =>
{
var setting = c.GetInstance<DatabaseSettings>();
setting.DbConnectionString =
System.Configuration.ConfigurationManager.AppSettings["DatabaseSettings.DBConnectionString"];
return setting;
});
}
}
Important: Your project will need to reference System.Configuration.
If you have a lot of settings you may want to conventionalize this pattern. We use the SettingsProvider out of FubuCore to make this a breeze. You simply have objects that end in Settings which get their properties automatically populated out of application settings. Chad Myers has a nice blog post on it.
Related
I'm not so sure that DryIoc is worth my time. It looks like lightweight and supported well in cross-platform environment (with Xamarin). But I feel a bit difficult working with it (in term of exploring everything myself).
The DryIoc community is also not very large (and by reading through some answers about DryIoc, I recognized that looks like there is only the author jumping in and giving the answers). Here is my problem as mentioned in the title. Suppose I have 2 ViewModel classes, the second has a property which should always match (mapped) with a property of the first, like this:
public class ParentViewModel {
}
public class FirstViewModel {
public FirstViewModel(ParentViewModel parent){
}
public string A {
//...
}
}
public class SecondViewModel {
public SecondViewModel(ParentViewModel parent){
}
public string A {
//...
}
}
Now I can use dryioc to register singleton for both ViewModels BUT for the second one, I also need to inject the property A with value from the first's property A as well.
container.Register<ParentViewModel>();
container.Register<FirstViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new FirstViewModel(Arg.Of<ParentViewModel>())));
container.Register<SecondViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new SecondViewModel(Arg.Of<ParentViewModel>())));
So as you can see the first registration should be fine because no property dependency is required. However the second one should have its A property depend on the A of the first one.
Really I cannot explore this myself. Injecting properties of some registered type is fine (and at least I know how to do that), but here the injected value is another property of some registered type.
Here is the straightforward way (but may be not the best one) to achieve that:
using System;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.Register<ParentViewModel>();
container.Register<FirstViewModel>(Reuse.Singleton);
container.Register<SecondViewModel>(Reuse.Singleton,
made: PropertiesAndFields.Of.Name("A", r => r.Container.Resolve<FirstViewModel>().A));
var firstVM = container.Resolve<FirstViewModel>();
firstVM.A = "blah";
var secondVM = container.Resolve<SecondViewModel>();
Console.WriteLine(secondVM.A); // should output "blah"
}
public class ParentViewModel {
}
public class FirstViewModel {
public FirstViewModel(ParentViewModel parent) { }
public string A { get; set; }
}
public class SecondViewModel {
public SecondViewModel(ParentViewModel parent) {}
public string A { get; set; }
}
}
In my opinion, the better and more simple way will the inversion of control: creating the A outside of both VMs and then injecting them into both.
I've just started playing with DapperExtensions and it looks very promising. However, I'm confused on how to handle registering the ClassMapper subclasses.
I have both a custom PluralizedAutoClassMapper and a regular ClassMapper and I'm trying to use both.
Here's my pluralized mapper...
public class CustomPluralizedMapper<T> : PluralizedAutoClassMapper<T>
where T : class
{
private readonly Type[] SinglularTablePocoTypes = new []{
typeof(LibraryInfo)
};
public override void Table(string tableName)
{
base.Table(tableName);
if(SinglularTablePocoTypes.Any(type => string.Equals(type.Name, tableName, StringComparison.CurrentCultureIgnoreCase)))
TableName = tableName;
}
}
...and here's the mapper specifically for the LibraryInfo class
public class LibraryInfoMapper : ClassMapper<LibraryInfo>
{
public LibraryInfoMapper()
{
Map(libraryInfo => libraryInfo.Name).Column("LibraryName");
Map(libraryInfo => libraryInfo.Description).Column("LibraryDescription");
AutoMap();
}
}
The PluralizedAutoClassMapper I get to work by calling the following...
DapperExtensions.DapperExtensions.DefaultMapper = typeof(CustomPluralizedMapper<>);
But I'm not sure how to use the other one at the same time. What am I missing?
Ok, I figured it out. The issue was because I'm using IoC and my POCOs are in a different assembly from the mappings.
In short, my model has no idea, nor cares about where or how it's being stored. It only defines an interface describing how it needs to interact with that storage. My DAL defines a class which implements that interface and uses SQLite as it's backing storage. Since the mappings only make sense in regards to SQLite, that's where I defined the mappings.
The problem is DapperExtensions reflects into the assembly that defines the POCOs looking for their ClassMappers, but since mine were in a different assembly, they weren't being found.
However, you can tell DapperExtensions to search external assemblies via the following line of code...
DapperExtensions.DapperExtensions.SetMappingAssemblies(new[]{
assemblyA, assemblyB, ...assemblyN
});
So since my mappings are defined in the same place as my static Mapper class (which has the static 'Initialize' call) all I now have to do is tell DapperExtensions to search there like so...
public static class Mappings
{
public static void Initialize()
{
DapperExtensions.DapperExtensions.DefaultMapper = typeof(CustomPluralizedMapper<>);
DapperExtensions.DapperExtensions.SetMappingAssemblies(new[]
{
typeof(Mappings).Assembly
});
}
public class CustomPluralizedMapper<T> : PluralizedAutoClassMapper<T>
where T : class
{
...
}
public class LibraryInfoMapper : ClassMapper<LibraryInfo>
{
...
}
}
And now everything works!
Better yet, since I can specify the table name in the LibraryInfoMapper, there's actually no need for my CustomPluralizedMapper and therefore I can just use the standard PluralizedAutoClassMapper like so...
public static class Mappings
{
public static void Initialize()
{
DapperExtensions.DapperExtensions.DefaultMapper = typeof(PluralizedAutoClassMapper<>);
DapperExtensions.DapperExtensions.SetMappingAssemblies(new[]
{
typeof(Mappings).Assembly
});
}
public class LibraryInfoMapper : ClassMapper<LibraryInfo>
{
public LibraryInfoMapper()
{
Table("LibraryInfo");
AutoMap();
}
}
}
Done and done! There was ZERO documentation on finding this out so I hope this helps others!
I've got something like this:
// This gets implemented by plugin authors to get callbacks about various things.
public interface ExternalPlugin
{
// This gets called by the main application to tell the plugin some data
// is available or similar.
void DoStuff(SomeDataBlob blob);
}
// Data blob for v1 of API
public class SomeDataBlob
{
internal SomeDataBlob(string prop) { Prop = prop; }
// Some piece of data that V1 plugins need
public string Prop { get; private set; }
}
// FUTURE!
// Data blob API v2 of API
public class SomeDataBlobV2 : SomeDataBlob
{
// Can be passed to clients expecting SomeDataBlob no problem.
internal SomeDataBlobV2(string prop, string prop2) :base(prop) { Prop2 = prop2; }
// Some piece of data that V2 plugins need. V2 plugins can cast to this from
// SomeDataBlob, but still can load successfully into older versions that support
// only V1 of the API
public string Prop2 { get; private set; }
}
I have to make SomeDataBlob public so that it can be used as a member of the public interface method ExternalPlugin.DoStuff. However, I would not like to allow clients to inherit from that class and thus be susceptible to the brittle base class problem. (All derivatives of that class should be kept in the same assembly)
Marking the class sealed goes too far because I believe removing sealed is a breaking API change; and even if that isn't, once I ship SomeDataBlobV2 clients could still do the wrong thing and inherit from SomeDataBlob directly.
Is there a way to enforce this kind of pattern?
Make the class internal, and expose an interface instead. Then use the factory pattern to create the correct implementation.
public interface ISomeDataBlob
{
}
internal class SomeDataBlob : ISomeDataBlob
{
}
public class BlobApiFactory
{
ISomeDataBlob Create();
}
You hide the implementation, but still give the user access to everything. You even make unit tests easier for your users ;)
Edit (answer to a comment from the OP)
What I effectively want is some method taking some parameters. I want to be able to add parameters that the main application can provide in a future version if the API without breaking clients. But I don't want clients to be able to create instances of the "parameters" class/interface or otherwise interact with it beyond receiving an instance of it as a parameter
Instead of hiding the APIs you can make sure that all object passed to your library originates from your assembly:
public class YourCoolService
{
public void DoSomething(ISomeDataBlob blob)
{
if (blob.GetType().Assembly != Assembly.GetExecutingAssembly())
throw new InvalidOperationException("We only support our own types");
}
}
Edit2
Just noticed that #RQDQ already provided that solution (didn't notice when answering your comment). If that's the solution you want, accept his answer instead.
/// <summary>
/// This is a dummy constructor - it is just here to prevent classes in other assemblies
/// from being derived from this class.
/// See http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2971840&SiteID=1
/// </summary>
internal MhlAdminLayer() { }
The idea is to have a constructor with no parameters internal. Then the class can't be derived from.
Edit: Sorry, the link in the comment doesn't work any more.
Edit 2:
http://msdn.microsoft.com/en-us/library/vstudio/ms173115.aspx
"You can prevent a class from being instantiated by making the constructor private ... "
If you are hell bent on not using sealed AND still using classes, you can enforce this at runtime. In otherwords, at your API boundary, inspect the classes involved and make sure they come from your assembly.
A simple example:
public void Bar(Foo foo)
{
if (foo.GetType().Assembly != this.GetType().Assembly)
throw new InvalidOperationException("It's not one of mine!");
}
public class Foo
{
}
As far as I know, interfaces are the way to do this. It would be an API breaking change, but it would mean you could do what you want.
public interface ExternalPlugin
{
void DoStuff(ISomeDataBlob blob);
}
// Interfaces:
public interface IDataBlob
{
string Prop { get; }
}
public interface IDataBlobV2 : IDataBlob
{
string Prop2 { get; }
}
// Data blob for v1 of API
internal class SomeDataBlob : IDataBlob
{
internal SomeDataBlob(string prop) { Prop = prop; }
public string Prop { get; private set; }
}
// FUTURE!
// Data blob API v2 of API
public class SomeDataBlobV2 : SomeDataBlob, IDataBlobV2
{
// Can be passed to clients expecting SomeDataBlob no problem.
internal SomeDataBlobV2(string prop, string prop2) : base(prop) { Prop2 = prop2; }
public string Prop2 { get; private set; }
}
And then to make the objects use the factory pattern, e.g.
public static class DataBlobFactory
{
public IDataBlob GetDataBlob(string prop)
{
return new SomeDataBlob(prop);
}
// so on.
}
What I would do is make some sort of factory class that exposes an interface that would pass an instance of whatever version for the specific API your client is using, and hide the implementation with an internal class
You can also use constraints to make it little easier to use, then the client can just put the Type of object they are looking for
public interface IBlobV1 { /*public stuff for V1 here*/ }
internal class BlobV1: IBlobV1 {/*v1 implementation*/ }
public interface IBlobV2 : IBlobV1 {/*public interface for V2 here*/ }
internal class BlobV2:BlobV1,IBlobV2 {/*v2 implementation*/}
public sealed BlobFactory
{
public IBlobV1 CreateVersion1Blob(){/* implementation */}
public IBlobV2 CreateVersion2Blob(){/* implementation */}
public T CreateBlob<T>()
where T: IBlobV1
{ /* implementation */}
}
SomeDataBlob can not be inherited because its only constructor is internal. If you try to implement a derived class in a client application:
class SomeDataBlobClient : SomeDataBlob
{
SomeDataBlobClient():base("TEST")
{
}
}
You will get the following error:
The type 'ClassLibrary1.SomeDataBlob' has no constructors defined
It seems that you solved your own problem.
I have an application which uses plugins. After creating several of them I've found that a big chunk of code is repeated here and there on them so I want to extract a super "plugin base".
Previous the refactor I had the following structure:
After the refactor I have the next one:
I currently don't find a way to model the fact that the plugin engine has a property settings of type plugin settings and the plugin engine base has a property settings of type plugin settings base. I feel that somehow should be a way to declare that the settings property of the plugin engine base should be a "cast" of the settings property of the plugin engine and to model the fact that they both are the same property.
I'm not sure if the problem is explained enough. Feel free to ask for clarifications.
Thanks.
You can use generics. Create generic base class and specify generic parameter constraint to be of type PluginSettingsBase.
abstract class PluginEngineBase<T>
where T: PluginSettingsBase
{
public abstract T Settings { get; set; }
}
Inherit from base class parametrized by PluginsSettings class (thus it is inherited from PluginSettingsBase)
class PluginEngine : PluginEngineBase<PluginsSettings>
{
public PluginSettings Settings { get; set; }
}
Same with PluginData.
An approach I found:
Base class:
class PluginEngineBase
{
public PluginSettingsBase Settings { get; set; }
}
Inheritor:
class PluginEngine : PluginEngineBase
{
public PluginSettings Settings
{
get
{
return (PluginSettings)base.Settings;
}
set
{
base.Settings = value;
}
}
}
Disclaimer: I'm quite new to DI and IoC, please forgive any drastic misunderstandings.
Consider a ClassB that requires a object implementing IClassA. Ninject should be able to inject instances of ClassA into the constructor of ClassB, assuming it can construct instances of ClassA:
public class ClassA : IClassA
{
public ClassA(string runtimeDependency) { /* ... */ }
}
public class ClassB : IClassB
{
public ClassB(IClassA depA) { /* ... */ }
}
public sealed class TestBootstrapModule : NinjectModule
{
public override void Load()
{
Bind<IClassA>().To<ClassA>();
Bind<IClassB>().To<ClassB>();
}
}
Now, let's say some runtime logic is involved in deriving the string runtimeDependency provided to ClassA. How should I provide Ninject with runtimeDependency so that it can provide ClassB with instances of ClassA?
The string will only be determined once, so I don't need to worry about injecting a new value into each instance.
One way to do it is to provide the ClassA via a method. Also keep in mind that with Ninject 2, you don't need modules and can do bindings directly in the Kernel.
Bind<IClassA>().ToMethod(_ =>
{
// do something interesting with a runtimeDependancy
return new ClassA(someInterestingVariable);
});
I'm really taking a stab as to when your runtime variable is available and it's scope.
There are a few options here depending on your design, and specific problem. The first, easiest solution is to just provide the value when you request your service from Ninject
Kernel.Get<IClassA>("runtimeDependencyValue");
If this is not possible however, things get a bit more interesting. The way I've solved this previously is to actually create contextual bindings to System.String itself.
Say if I want to bind a connection string, I'll create a custom attribute:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class ConnectionStringAttribute : Attribute
{
/// <summary>
/// Denotes the setting that you want to populate the given property with.
/// </summary>
public string SettingName { get; private set; }
public ConnectionStringAttribute(string configSettingName = "")
{
SettingName = configSettingName;
}
}
and then I decorate my service constructor like this:
public class ClassA : IClassA
{
public ClassA([ConnectionString("AppDB")] string runtimeDependency) { /* ... */ }
}
Finally, my binding will look something like this:
Bind<string>()
.ToMethod(ctx =>
{
var attr = (ConnectionStringAttribute)context.Request.Target.GetCustomAttributes(typeof(ConnectionStringAttribute), true).First();
string settingName = string.IsNullOrEmpty(attr.SettingName) ? context.Request.Target.Name : attr.SettingName;
return ConfigurationManager.ConnectionStrings[settingName].ConnectionString;
})
.WhenTargetHas<ConnectionStringAttribute>();
You get the idea. Hope this helps :)