Providing Ninject with constructor dependencies it can't resolve? - c#

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 :)

Related

How do you register DapperExtension ClassMapper subclasses so they are used?

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!

Structuremap all instances of abstract

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.

Can I disallow other assemblies from inheriting from a class?

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.

Is it possible to create an instance of an class without running ANY code from the class? (no ctor, no field initializations)

I have created an engine that takes in 3rd party plugins (DLL's) that implement an interface.
Since I have no control over the code that gets plugged in, I want to be able to run 1 specific method (from the interface) from the correct class (GetTypes loop untill I find the interfaced class ).
Since anyone can create nice constructor code that executes on Activator.CreateInstance, I can solve that by using FormatterServices.GetUninitializedObject. But that does not help when code is being initialized on fields in the class.
public class myclass : myinterface {
public someotherclass name = new someotherclass()
public myclass() {
//Unknown code
}
//I only want this run.
public string MyProperty{
get {
return "ANiceConstString";
}
}
}
The problem with both ways (CreateInstance/GetUninitializedObject) is that the constructor of someotherclass will be run.
Before you start analyze my needs. This is only run in the initializing of the engine to get a set of standard values. If this get'er relies on other initialized values the "plugin" will be marked as failed as there is no valid value returned. If not marked as failed, later on the class will be loaded properly with Activator.CreateInstance().
So stick to this question:
Does .Net support any way to create an 100% non-initialized class?
Update for the answers. I tested this before I posted my question.
For the answer that someotherclass wont run, I allready tested that and it is run if static.
public class myclass : myinterface {
static Tutle test;
public myclass () {
test = new Tutle();
}
public class Tutle {
public Tutle() {
MessageBox.Show("RUN!");
}
}
}
CreateInstance shows the messagebox. GetUninitializedObject does not.
public class myclass : myinterface {
static Tutle test = new Tutle();
public myclass () {
}
public class Tutle {
public Tutle() {
MessageBox.Show("RUN!");
}
}
}
CreateInstance shows the messagebox. GetUninitializedObject shows the messagebox.
Is there a way to get around static field intializers and ctors?
Simply:
var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass));
That will not run the constructor / field initializers. At all. It will not run the constructor for someotherclass; name will be null.
It will, however, execute any static constructor that exists, if necessary under standard .NET rules.
HOWEVER! I should note that this method is not intended for ad-hoc usage; its primary intent is for use in serializers and remoting engines. There is a very good chance that the types will not work correctly if created in this way, if you have not subsequently taken steps to put them back into a valid state (which any serializer / remoting engine would be sure to do).
As an alternative design consideration:
[SomeFeature("ANiceConstString")]
public class myclass : myinterface {
public someotherclass name = new someotherclass()
public myclass() {
//Unknown code
}
}
Now you can access the feature without instantiation; just use:
var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
type, typeof(SomeFeatureAttribute));
string whatever = attrib == null ? null : attrib.Name;
with:
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public sealed class SomeFeatureAttribute : Attribute
{
private readonly string name;
public string Name { get { return name; } }
public SomeFeatureAttribute(string name) { this.name = name; }
}

Configuring an Autofac delegate factory that's defined on an abstract class

I'm working on a C# project. I'm trying to get rid of a Factory class that has a large switch statement.
I want to configure Autofac to be able to construct a dependency based on a parameter, thereby allowing Autofac to take the place of the Factory.
I've looked at the DelegateFactories page of the Autofac wiki, but I can't figure out how to apply the pattern to an abstract class. Here's some code showing the situation:
public enum WidgetType
{
Sprocket,
Whizbang
}
public class SprocketWidget : Widget
{
}
public class WhizbangWidget : Widget
{
}
public abstract class Widget
{
public delegate Widget Factory(WidgetType widgetType);
}
public class WidgetWrangler
{
public Widget Widget { get; private set; }
public WidgetWrangler(IComponentContext context, WidgetType widgetType)
{
var widgetFactory = context.Resolve<Widget.Factory>();
Widget = widgetFactory(widgetType);
}
}
I'd like it if I were to say new WidgetWrangler(context, WidgetType.Sprocket), its Widget property would be a SpocketWidget.
When I try this, I get errors stating that Widget.Factory is not registered. Does this delegate factory pattern not work with abstract classes, and if so, is there another way to accomplish this?
What you're looking for is the IIndex<,> Relationship Type.
If you register your sub-classes with .Keyed<>(...) you can key a registration to a value (object).
For example:
builder.RegisterType<SprocketWidget>()
.Keyed<Widget>(WidgetType.Sproket)
.InstancePerDependency();
builder.RegisterType<WhizbangWidget>()
.Keyed<Widget>(WidgetType.Whizbang)
.InstancePerDependency();
Then you only require a dependency of IIndex<WidgetType,Widget> to mimic factory behaviour.
public class SomethingThatUsesWidgets
{
private readonly IIndex<WidgetType,Widget> _widgetFactory;
public SomethingThatUsesWidgets(IIndex<WidgetType,Widget> widgetFactory)
{
if (widgetFactory == null) throw ArgumentNullException("widgetFactory");
_widgetFactory = widgetFactory;
}
public void DoSomething()
{
// Simple usage:
Widget widget = widgetFactory[WidgetType.Whizbang];
// Safe Usage:
Widget widget2 = null;
if(widgetFactory.TryGetValue(WidgetType.Sprocket, out widget2))
{
// do stuff
}
}
}
That's using Dependency Injection approach, if you just want to resolve the factory:
var factory = Container.Resolve<IIndex<WidgetType,Widget>>();

Categories

Resources