How to use a lambda to specify a constructor argument? - c#

I am not overly familiar with implementing lambdas and expressions, but I've used to this syntax many times in MVC where the lambda is identifying a property on an object:
Html.Label(model => model.Foo)
In my app I am using Ninject conditional bindings to supply the instance of the Settings class which is injected when I request an instance of Class. My Class looks like this:
public class Class
{
private readonly Settings settings;
public Settings Settings { get { return settings; } }
public Class(Settings settings)
{
this.settings = settings;
}
}
I have some code which looks like this to get an instance of Class. I am aware this is the service locator anti pattern, but we have no choice in this case due to other constraints:
var settings = new Settings();
var instance = Ioc.Instance.Get<Class>("settings", settings);
I would like to refactor it to look like this so that it is strongly typed, using a lambda to specify which argument on the constructor I am supplying:
var settings = new Settings();
var instance = Ioc.Instance.Get<Class>(x => x.settings, settings);
So, is this possible, and what would the code look like?

Conceptually there is a lack of the factory (factory interface), so it should be introduced to avoid using the container directly.
The Ninject Factory (factory interface) extension could be used to create the instance, as follows:
Declare a factory interface:
public interface IFactory
{
Class Create(Settings settings);
}
Add a binding to the composition root:
kernel.Bind<IFactory>().ToFactory();
Use the factory to get an instance:
var settings = new Settings();
var factory = Ioc.Instance.Get<IFactory>();
var instance = factory.Create(settings);
Please see the ninject/ninject.extensions.factory for the alternatives.

The problem with constructor argument names and expressions is, that an expression is only valid / complete when it covers all parameters of the constructor. Now i suppose you want to inject a few of the parameters (have ninject handle them) and for one or two specific parameters you want to pass a value, let's say it looks like:
public interface IFoo { }
public class Foo : IFoo
{
public Foo(IServiceOne one, IServiceTwo two, string parameter) {...}
}
Ninject supports ctor expressions, but only for bindings, and they work like this:
IBindingRoot.Bind<IFoo>().ToConstructor(x =>
new Foo(x.Inject<IServiceOne>(), x.Inject<IServiceTwo>(), "staticArgument");
so instead of only specifying the "staticArgument" which you are interested in, you also have to specify IServiceOne and IServiceTwo. What if the constructor changes? Well the call needs to be adapted as well! Lot of work for just passing a single simple parameter.
Now if you still want to do this i'd suggest having a look at the ToConstructor code and creating a similar extension for a Get call which will translate some call
IResolutionRoot.Get<IFoo>(x =>
new Foo(
x.Ignore<IServiceOne>(),
x.Ignore<IServiceTwo>(),
x.UseValue("mystring"));
to
IResolutionRoot.Get<IFoo>(new ConstructorArgument("parameter", "mystring"));
However, i would suggest going with #Sergey Brunov 's answer and use Ninject.Extensions.Factory. Now I think your going to say that it's no good because you'll still have to specify the parameter name,.. which is not refactor safe and a hassle (no code completion...).
However, there's a solution to the problem: Instead of using a constructor argument which "matches" the name of the argument, you can use a type matching argument.
Ok, there's a catch. If you've got multiple arguments of the same type,.. well it won't work. But i think that's seldomly the case and you can still introduce a container data-class to address it:
public class FooArguments
{
string Argument1 { get; set; }
string Argument2 { get; set; }
}
Now how can you use type matching?
There's two ways:
Use a Func<string, IFoo> factory. Just inject Func<string, IFoo> into where you want to create and IFoo.
Extend the Factory extension. Yes you've heard right ;-) It's actually not that difficult. You "just" need to implement a custom IInstanceProvider (also see http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/) so you can something like:
public interface IFooFactory
{
IFoo Create([MatchByType]string someParam, string matchByName);
}
(==> use an attribute to tell the factory extension how to pass the parameter to the Get<IFoo>request).

Look at following article -
http://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/
Specifically
public static class Extensions
{
public static string GetPropertyName<T,TReturn>(this Expression<Func<T,TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
}
Note - This method may not work for all possible ways in which one can use expressions to indicate a property name for a class, and hence may need to be enhanced based on your needs (how generic you need it to be).
But essentially, once you have this helper method, your call becomes
var settings = new Settings();
Ioc.Instance.Get<Class>(GetPropertyName(x => x.settings), settings);

Related

Passing a new instance of a Type through a Generic Method

I have a series of very similar methods:
private static DocumentBody GetPdfBodyObject(int sectionId)
{
DocumentBody db = new DocumentBody();
// Add some stuff to Db
return db;
}
private static DocumentHeader GetPdfHeaderObject(int sectionId)
{
DocumentHeader dh = new DocumentHeader();
// Add some stuff to DH - similar to above
return dh;
}
And so on...
As you can see the difference between these two examples is based around the Type that is being instantiated & returned.
So instantly I thought to use a Generic Method to reduce the code duplication... I just cant seem to figure out which way is the 'best practice' and can I get what I need without using reflection?
I haven't used Generic Methods much at all so any advice is welcome.
The best practice here would be to refactor static methods to factory methods or use builder pattern if it's a bigger object you're building (which it appears to be the case). The use of generic methods would be limited here to parameterless constructors - whenever the constructor would take parameters, you'd need to use the Activator, which is reflection and you generally do not want such code. Having said that: the two methods you gave construct objects using parameterless constructors, so you can refactor both to:
private static TT GetPdfObjectPart<TT>(int sectionId) where TT : class, new()
{
TT dh = new TT();
// Add some stuff to DH - similar to above
return dh;
}
Also note, that as #dymanoid pointed out - in this case you can only use what is the part of the contract (the where clause) - so you'd need to implement
some 'generic' interface to all constructed types - and you'd be limited to methods from the interface. It really looks like you're in classical situation to use the builder pattern.
As for me, interfaces are good:
private interface IDocumentPart
{
}
private class DocumentHeader : IDocumentPart
{
}
private class DocumentBody : IDocumentPart
{
}
private static T GetPdfPart<T>(int sectionId) where T : IDocumentPart, new()
{
var doc = new T();
return doc;
}
Of course, you can define some properties and methods common for all your classes in an interface.

Factory Pattern, selecting by Property

I have a (growing) list of Data-Generators. The generator that I need is created by a factory class. The generators all implement a common Interface, which includes among other things a static string name.
What I would like to do: Call the factory.Create method with a string parameter for the above mentioned name. The create method finds the generator with this name and returns a new instance of said generator.
Bonus in my opinion of this way to do it: I only have to add new generator classes without having to edit the factory.
Question:
Is this a good way to handle this problem?
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Is it correct to call this way of working a factory, or is this some different pattern?
In the end I would call the factory like this (simplified):
//Caller
public DataModel GetData2()
{
var generator = new DataFactory().Create("Gen.2");
return generator.GetData();
}
//Factory
public class DataFactory
{
public AbstractDataGenerator Create(string type)
{
//Here the magic happens to find all implementations of IDataGenerator
var allGenerators = GetImplementations();
var generator = allGenerators.FirstOrDefault(f => f.name == type);
if (generator != null)
return (AbstractDataGenerator)Activator.CreateInstance(generator);
else
return null;
}
}
//Interface
public abstract class AbstractDataGenerator
{
public static string name;
public abstract DataModel GetData();
}
//Data-Generators
public class DataGen1 : AbstractDataGenerator
{
public static string name = "Gen.1";
public DataModel GetData()
{
return new DataModel("1");
}
}
public class DataGen2 : AbstractDataGenerator
{
public static string name = "Gen.2";
public DataModel GetData()
{
return new DataModel("2");
}
}
Should the magic GetImplementations() in the factory be done via Reflection or somehow different? Should I use a completely different approach?
Since answers refer to IoC and DI: This project uses NInject already, so it would be available.
Switched from interface to abstract class.
Is this a good way to handle this problem?
Having a factory to get an instance of the logic class you need by some key - I believe it is a good way. It is a pattern that I use a lot myself. About the way you have your key - I'd prefer to not have it as a static member (regardless to the fact that interfaces can't have static members) but just as a property and to add a base class to the IDataGenerator. That base class will have a constructor that will get the name - That way each new DataGenerator you create will have to set it and you wont forget.
About having the name as a string - I personally prefer having it "strongly typed". What I mean is that if I pass Gen . 2 instead of Gen.2 with strings I will discover this problem only in runtime. Possible other ways (if you want, because a simple string is fine too - a matter of taste):
Replace strings with an enum
Have a static class with static readonly strings for all your values - then in your code use those values. You get the benifits of the intellisense and of not getting the string wrong but better than enum - you can just still pass strings that are not in the "list" so you can add new ones as add-ons.
Have a RequestGenerator object, with each Generator being IDataGenerator<TGeneratorRequest>. This might be an overkill but if you have also extra information you need for the creating of a DataGenerator which differs between them then consider it .
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Yes, reflection can be a good way to do so. However, I would suggest to read into Dependency Injection and IoC Containers like Castle Windsor for example. There are things out there that already implement it for you, so why to re-invent the wheel :)
DI is a life changer concept in my opinion
Is it correct to call this way of working a factory, or is this some different pattern?
Yap. It is a Factory
Should the magic GetImplementations() in the factory be done via Reflection or somehow different?
See answer for question 2
This is where constructor injection can REALLY shine. Look into dependency injection tools and employ one! It also checks your "Bonus" request.
Here's what your factory might look like with constructor injection:
public class DataFactory
{
private Dictionary<string, IDataGenerator> generators;
public DataFactory(IDataGenerator[] generatorReferences)
{
this.generators = generatorReferences
.ToDictionary(k => k.name, v => v);
}
public IDataGenerator Create(string type)
{
IDataGenerator generator = null;
this.generators.TryGetValue(type, out generator);
return generator;
}
}
Most DI software has the capability to automatically scan assemblies for implementations of a certain type (e.g. IDataGenerator) and register those with itself, when it constructs an instance of your DataFactory it'll automatically include them.

How to use generics to handle type-specific configurations in an Action<IBuilder<T>>?

I am trying to implement a complex builder to help my testing context. To do that I refactored my code to have a method :
public TestContext Add<T>(Action<IBuilder<T>> configurator) where T : class, new()
{
IBuilder<T> builder = CreateBuilderOf<T>();
configurator(builder);
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
The problem arises when I need to specify the configuration when calling the method :
TestContext.Instance.Add<Person>(personBuilder => ((PersonBuilder)personBuilder).Name("SMITH"));
I need to be able to use type specific methods in the configurator, which are implemented by the concrete builders, such as :
public PersonBuilder : IBuilder<Person>
{
private Person Item;
public PersonBuilder() { Item = new Person(); }
public Name(string mame) { Item.Name = name; }
public Person GetItem() { return Item; }
}
Apparently, passing an Action<PersonBuilder> as an Action<IBuilder<Person>> is not allowed, even though PersonBuilder implements IBuilder<Person>, hence the cast.
I would very much like to either :
Need not to cast inside the lambda but rather at the start of it, e.g.
(PersonBuilder personBuilder) => personBuilder.Name("SMITH"), but that boils down to being an instance of Action<PersonBuilder> and therefore is equally invalid;
Use a function such as BuildSimplePerson(PersonBuilder builder) in Add's argument : Add<Person>(BuildSimplePerson)
I think I can do a type casting through two BuildSimplePersons implementations such as :
private void BuildSimplePerson(IBuilder<Person> builder)
{
BuildSimplePerson(builder as PersonBuilder);
}
private void BuildSimplePerson(PersonBuilder builder)
{
builder.Name("SMITH");
}
But that is not really an elegant solution.
I also realize passing Action<PersonBuilder> as an Action<IBuilder<Person>> is incorrect because we don't know if the argument to that function will truly be a PersonBuilder or any other implementation of IBuilder<Person>.
How can I do better ?
As my comment already states, the problem is that your current code assumes that CreateBuilderOf<T> returns a PersonBuilder but it could actually return anything that implements IBuilder<Person> in which case your cast would fail.
Your code looks like it is generic, but in fact, it is not. You always want to work on the concrete class (PersonBuilder) and not on the general interface IBuilder<Person>.
My understanding is, that you want one generic Add<T> method to avoid having to repeat that code inside it for each type.
Here is my approach:
public TestContext Add<T>(IBuilder<T> builder) where T : class, new()
{
T item = builder.GetItem();
RepositoryOf<T>().Insert(item);
SetCurrent(item);
return this;
}
You would call it like this:
TestContext.Instance.Add<Person>(CreatePersonBuilder().Name("SMITH"));
Obviously, you would need to have a CreateXBuilder method for each type that you want to be able to add. However, I think you already have this at least implicitly, because I would assume that your CreateBuilderOf<T> method is one huge switch statement anyway.
If you don't want to create such methods, another approach to get the builder would be a generic method like so:
CreateBuilder<PersonBuilder>()
But really, this is actually nothing more than a new PersonBuilder(), so you actually could simply go with
TestContext.Instance.Add<Person>(new PersonBuilder().Name("SMITH"));
The Configure method would be very similar:
TestContext.Instance.Configure<Person>(id, p => new PersonBuilder(p).Name("SMITH"));
This would pass the ID, which the Configure method would use to look up the object, which in turn is passed to the callback. So the second parameter of Configure would not be a Action<IBuilder<T>> but an Action<T>.
This approach has another advantage over your existing code:
Your existing code assumes not just that PersonBuilder will be the implementation used for IBuilder<Person>. No, your code also assumes that it has a constructor without parameters and one which takes a Person. These assumptions are impossible for the compiler to verify.
With the code I showed above, a builder implementation could take additional parameters without problems and the compiler would verify that everything is alright.

Binding multiple versions of the same type with Ninject

I am using Ninject to create a set of "plugins", e.g. I have:
Bind<IFoo>().To<Class1>();
Bind<IFoo>().To<Class2>();
Bind<IFoo>().To<Class3>();
... and later on I use kernel.GetAll<IFoo>() and iterate over the results. Each of Class1/Class2/Class3 implement IFoo of course, and have constructors that have a bunch of parameters also injected by Ninject, for example the constructor for Class1 is public Class1(IBar bar, IBaz baz), with both IBar and IBaz injected by Ninject. So far so good.
However, now I want to have two different "versions" of Class1, both bound to IFoo, differing only in a value passed at construction time. That is, for example, suppose the Class1 constructor was now public Class1(IBar bar, IBaz baz, bool myParameter), and I want to do the following:
Bind<IFoo>().To<Class1>(); //Somehow pass 'true' to myParameter here
Bind<IFoo>().To<Class1>(); //Somehow pass 'false' to myParameter here
Bind<IFoo>().To<Class2>();
Bind<IFoo>().To<Class3>();
... Then, when I call kernel.GetAll<IFoo>(), I want 4 versions of IFoo returned (Class1 "true" version, Class1 false version, Class2 and Class3). I've read through the Ninject documentation and can't find a way to do this.
Here are some ideas I tried, but none of them work well:
1) I could just separate classes (e.g. Class1True and Class1False), with one deriving from another, and bind to them. The problem is that this solution doesn't really scale when I have to do this for many classes - I end up polluting my class hierarchy with a lot of useless classes, and the problem becomes worse when the constructor parameter I want to pass is anything more complex than a bool. Realistic example:
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '5' to brushThickness to create a fine brush
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '25' to brushThickness to create a medium brush
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '50' to brushThickness to create a coarse brush
Bind<IDrawingTool>().To<Pencil>();
Bind<IDrawingTool>().To<SprayCan>();
Of course, this is just one possible configuration of infinitely many possible ones. Creating a new class for each brush thickness seems wrong.
2) I looked into the possibility of using a .ToMethod binding, something like this:
Bind<IDrawingTool>().ToMethod(c => new Brush(5));
Bind<IDrawingTool>().ToMethod(c => new Brush(25));
Bind<IDrawingTool>().ToMethod(c => new Pencil());
But in this case I'm confused about the following:
a) What if the Brush() constructor actually requires other parameters as well, that must be injected via Ninject?
b) Are multiple ToMethod bindings actually allowed?
c) Would this work with InSingletonScope()?
So to summarize: What is a good way to bind to multiple "versions" of the same type?
It's perfectly fine to create two bindings for the same type, which differ only in parameters.
So what you've got to do is:
Bind<IFoo>().To<Class1>().WithConstructorArgument("boolParameterName", true);
Bind<IFoo>().To<Class1>().WithConstructorArgument("boolParameterName", false);
Use the WithConstructorArgument to pass the parameter. You can either have Ninject match the parameter by the name - in the above example the Class1 ctor would need to feature a bool parameter whose name is exactly boolParameterName. Or you can match the type, in which case you could only have one parameter of that type in the constructor. Example: WithConstructorArgument(typeof(bool), true).
All the parameters which you don't specify by WithConstructorArgument get ctor-inject "as usual".
Complete working example (using xunit and FluentAssertions nuget packages):
public interface IBar { }
public class Bar : IBar { }
public interface IFoo { }
class Foo1 : IFoo
{
public Foo1(IBar bar) { }
}
class Foo2 : IFoo
{
public Foo2(IBar bar, bool theParametersName) { }
}
[Fact]
public void FactMethodName()
{
var kernel = new StandardKernel();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IFoo>().To<Foo1>();
kernel.Bind<IFoo>().To<Foo2>().WithConstructorArgument("theParametersName", true);
kernel.Bind<IFoo>().To<Foo2>().WithConstructorArgument("theParametersName", false);
List<IFoo> foos = kernel.GetAll<IFoo>().ToList();
foos.Should().HaveCount(3);
}
If you don't use any conditional bindings, resolving those "multiple versions" at runtime when the container detects a dependency will result in an exception, due to ambiguity. It surely could work in a "service-locator"-based access, but in true DI composing the object graph, you'll run into trouble using this approach.
In your depicted scenario, this ambiguity would arise should the following hypothetical situation existed:
public class MyDraw
{
public MyDraw(IDrawingTool drawingTool)
{
// Your code here
}
}
kernel.Bind<IDrawingTool>().ToMethod(c => new Brush(5));
kernel.Bind<IDrawingTool>().ToMethod(c => new Brush(25));
kernel.Bind<IDrawingTool>().ToMethod(c => new Pencil);
// Runtime exception due to ambiguity: How would the container know which drawing tool to use?
var md = container.Get<MyDraw>();
However, if you have this class to be injected:
public class MyDraw
{
public MyDraw(IEnumerable<IDrawingTool> allTools)
{
// Your code here
}
}
This would work due to multi-injection. The caontainer would simply invoke all bindings that match IDrawingTool. In this case, multiple bindings are allowed, even ToMethod(...) ones.
What you need to do is rely upon mechanisms such as Named Bindings or Contextual Bindings (using WhenXXX(...) syntax, to let the target of injection to determine which concrete implementation it requires. Ninject has extensive support for this and actually is one of the defining features for it's core DI Framework. You can read about it here.

Factory Creating Objects According to a Generic Type C#

What would be the most efficient way to instanciate an object according to a generic type passed to a Factory class, for instance:
public class LoggerFactory
{
public static ILogger<T> Create<T>()
{
// Switch Statement?
// Generic Dictionary?
// EX.: if "T" is of type "string": return (ILogger<T>)new StringLogger();
}
}
How would you do it? Which branching statement? etc...
I think it's best to keep it simple, perhaps something like this:
public static class LoggerFactory
{
static readonly Dictionary<Type, Type> loggers = new Dictionary<Type, Type>();
public static void AddLoggerProvider<T, TLogger>() where TLogger : ILogger<T>, new()
{
loggers.Add(typeof(T), typeof(TLogger));
}
public static ILogger<T> CreateLogger<T>()
{
//implement some error checking here
Type tLogger = loggers[typeof(T)];
ILogger<T> logger = (ILogger<T>) Activator.CreateInstance(tLogger);
return logger;
}
}
You just call the AddLoggerProvider for each type you want to support, can be extended at runtime, it ensures you definetly add an implementation of the interface to the library and not some object, isn't very fast because of the Activator, but creating a logger wont likely be a bottleneck anyway. Hope it looks okay.
Usage:
// initialize somewhere
LoggerFactory.AddLoggerProvider<String, StringLogger>();
LoggerFactory.AddLoggerProvider<Exception, ExceptionLogger>();
// etc..
ILogger<string> stringLogger = LoggerFactory.CreateLogger<string>();
Note: each ILogger<T> requires a parameterless constructor for the Activator, but that too is ensured with the new() generic constraint in the add method.
I think I'd do it like this:
public class LoggerFactory<T>
{
private static Dictionary<Type, Func<ILogger<T>>> LoggerMap =
new Dictionary<Type, Func<ILogger<T>>>
{
{ typeof(string),
() => new StringILogger() as ILogger<T> },
{ typeof(StringWriter),
() => new StringWriterILogger() as ILogger<T> }
};
public static ILogger<T> CreateLogger()
{
return LoggerMap[typeof(T)]();
}
}
You pay something of a readability price (all those angle brackets, sheesh), but as you can see it makes for very little program logic.
Although I typically would recommend using a dependency injection framework, you could implement something with reflection that would search the available types for one that implements the appropriate ILogger interface.
I would suggest that you carefully consider which assemblies will contain these logger implementations and how extensible and bullet-proof you want the solution to be. Performing runtime searches across the available assemblies and types is not inexpensive. It is, however, an easy way to allow extensibility in this type of design. It also avoid the issue of up-front configuration - however it requires that only a single concrete type implement a particular version of the ILogger<> interface - otherwise there's an ambiguous situation you have to resolve.
You may want to perform some internal caching to avoid the expense of performing reflection on each call to Create().
Here is some sample code you could start with.
using System;
using System.Linq;
using System.Reflection;
public interface ILogger<T> { /*... */}
public class IntLogger : ILogger<int> { }
public class StringLogger : ILogger<string> { }
public class DateTimeLogger : ILogger<DateTime> { }
public class LoggerFactory
{
public static ILogger<T> Create<T>()
{
// look within the current assembly for matching implementation
// this could be extended to search across all loaded assemblies
// relatively easily - at the expense of performance
// also, you probably want to cache these results...
var loggerType = Assembly.GetExecutingAssembly()
.GetTypes()
// find implementations of ILogger<T> that match on T
.Where(t => typeof(ILogger<T>).IsAssignableFrom(t))
// throw an exception if more than one handler found,
// could be revised to be more friendly, or make a choice
// amongst multiple available options...
.Single();
/* if you don't have LINQ, and need C# 2.0 compatibility, you can use this:
Type loggerType;
Type[] allTypes = Assembly.GetExecutingAssembly().GetTypes();
foreach( var type in allTypes )
{
if( typeof(ILogger<T>).IsAssignableFrom(type) && loggerType == null )
loggerType = type;
else
throw new ApplicationException( "Multiple types handle ILogger<" + typeof(T).Name + ">" );
}
*/
MethodInfo ctor = loggerType.GetConstructor( Type.EmptyTypes );
if (ctor != null)
return ctor.Invoke( null ) as ILogger<T>;
// couldn't find an implementation
throw new ArgumentException(
"No mplementation of ILogger<{0}>" + typeof( T ) );
}
}
// some very basic tests to validate the approach...
public static class TypeDispatch
{
public static void Main( string[] args )
{
var intLogger = LoggerFactory.Create<int>();
var stringLogger = LoggerFactory.Create<string>();
var dateTimeLogger = LoggerFactory.Create<DateTime>();
// no logger for this type; throws exception...
var notFoundLogger = LoggerFactory.Create<double>();
}
}
Depends on how many types you intend to handle. If it's small (less than 10) I'd suggest a switch statement, as it'll be fast and cleaner to read. If you want more you would want a lookup table (Hash Map, Dictionary, etc), or some reflection based system.
switch statement vs dictionary - doesn't matter for perfomance, as a switch is compiled into a dictionary. So really it's a matter of readabilty and flexibility. The switch is easier to read, on the other hand a dictionary can be extended at runtime.
You might consider using a dependency injection framework here like Unity. You can configure it with the generic types that your factor will return and do the mapping in configuration. Here's an example of that.
1) I'm always amazed at the complexity people put into logging. Always seems like overkill to me. If log4net is opensource, I'd recommend you go look at that, infact, you might just as well use it ...
2) Personally, I try to avoid type checking whenever possible - it defeats the point of generics. Just use the .ToString() method and be done with it.
Hrm... you could actually try to be a little more clever about this, depending on what the given runtime system supported. I actually try to avoid any conditional statements in my code if I can, especially in polymorphic and dynamically bound code. You've got a generic class there, so why not use it?
For example, in Java, you can especially make use of the static method you've got there to do something like this:
public class LoggerFactory<T>
{
public static ILogger<T> CreateLogger(Class<? extends SomeUsefulClass> aClass);
{
// where getLogger() is a class method SomeUsefulClass and its subclasses
// and has a return value of Logger<aClass>.
return aClass.getLogger();
// Or perhaps you meant something like the below, which is also valid.
// it passes the generic type to the specific class' getLogger() method
// for correct instantiation. However, be careful; you don't want to get
// in the habit of using generics as variables. There's a reason they're
// two different things.
// return aClass.getLogger(T);
}
}
You'd call it like this:
public static void main(String[] args)
{
Logger = LoggerFactory.createLogger(subclassOfUsefulClass.class);
// And off you go!
}
This avoids having to have any conditionals and is more flexible besides: any class that's a subclass (or implements the logger interface, perhaps) of SomeUsefulClass can return the correctly typed logger instance.

Categories

Resources