Why is my implementation always calling the same derived class? - c#

I have a base class that accepts a Type as a constructor argument, and two derived classes that inherit from that base class. I also have an interface of that base class, that I inject to use in other places.
When I call the base method "FormatValue", passing different types as parameters, I always get the same result (it call the method in one of the classes, ignoring my type parameter).
What am I doing wrong?
public interface IFormatService
{
string FormatValue(object value);
}
public abstract class FormatService : IFormatService
{
protected FormatService(Type type)
{ }
public abstract string FormatValue(object value);
}
public static class Program
{
private static void Main(string[] args)
{
var serviceProvider = new ServiceCollection()
.AddSingleton<IFormatService, CurrencyFormat>()
.AddSingleton<IFormatService, DateTimeFormat>()
.BuildServiceProvider();
var formatService = serviceProvider.GetService<IFormatService>();
Console.WriteLine(formatService.FormatValue(DateTime.Now));
Console.WriteLine(formatService.FormatValue(200));
Console.ReadLine();
}
}
public class CurrencyFormat : FormatService
{
public CurrencyFormat() : base(typeof(decimal))
{
}
public override string FormatValue(object value) => "CurrencyFormatter";
}
public class DateTimeFormat : FormatService
{
public DateTimeFormat() : base(typeof(DateTime))
{
}
public override string FormatValue(object value) => "DateTimeFormatter";
}
Current result:
DateTimeFormatter
DateTimeFormatter
Expected result:
DateTimeFormatter
CurrencyFormatter

Code pointed below overrides your previous CurrencyFormat registration, so it always resolves to DateTimeFormat.
var serviceProvider = new ServiceCollection()
.AddSingleton<IFormatService, CurrencyFormat>()
.AddSingleton<IFormatService, DateTimeFormat>() <---------
.BuildServiceProvider();

If you want to call different methods depending on the type of parameter, there are many ways to do it.
One way is by using the dynamic that choose the best overload at runtime:
public interface IFormatService
{
string FormatValue(object value);
}
public class FormatService : IFormatService
{
public string FormatValue(object value)
{
dynamic valueAsDynamic = value;
return FormatValueDynamic(valueAsDynamic);
}
string FormatValueDynamic(dynamic value) => FormatValuePrivate(value);
string FormatValuePrivate(DateTime value) => "DateTimeFormatter";
string FormatValuePrivate(decimal value) => "CurrencyFormatter";
string FormatValuePrivate(object value) => throw new NotSupportedException();
}
This way you can add all the methods you need.

Related

Know what derived to cast to a base class in c# with generics

I am making a command handler in .NET CORE.
I have a base abstract class:
public abstract class ConsoleCommandBase
{
public string CommandName;
public bool FailsOnBadArgument;
public abstract void Execute(string[] args);
}
And a few classes that inherit from it so
public class ConsoleCommand<T> : ConsoleCommandBase
{
private Action<T> Action;
public ConsoleCommand(string commandName,Action<T> action)
{
CommandName = commandName;
Action = action;
}
public override void Execute(string[] args)
{
//Expected Arguments are 1 so check if args has at least a length of 1
if (args.Length < 1)
{
Console.WriteLine($"{CommandName} could not be executed too few arguments were present.");
return;
}
Action?.Invoke(GenericConversion<T>.GetValueFromString(args[0]));
}
}
I have ConsoleCommand<T..Tn> but all of them are structured the same way.
The generic conversion class is just a simple try catch that attempts to convert the
string value to whatever T is with (T) Convert.ChangeType(var,typeof(T))
Now the problem:
All the commands are stored in a List<ConsoleCommandBase>
and then are converted to whatever type they where when added with if statements so:
if (consoleCommand is ConsoleCommand<string> command1)
{
command1.Execute(args);
return true;
}
The problem is that this does not scale very well for example if I use four types so [int,bool,string,float]
for my ConsoleCommand<T> are only 4 if statements but for ConsoleCommand<T,T1,T2,T3> are already over 300 if statements and it grows very rapidly.
I know there must be an easier way of doing this, because right now I can use a code generator and generate the if statements in an instant but having a 5000 lines code file does not seam to be the proper way of doing things.
You can put a lot more functionality into your base class:
public abstract class ConsoleCommandBase
{
public string CommandName;
public bool FailsOnBadArgument;
protected abstract Type[] Types { get; }
public int TypeCount => Types.Length;
protected ConsoleCommandBase(string commandName) => CommandName = commandName;
public void Execute(string[] args)
{
if (args.Length != Types.Length)
{
Console.WriteLine($"{CommandName} could not be executed too few arguments were present.");
return;
}
var objects = args.Zip(Types).Select((value, type) => Convert(value, type)).ToArray();
Execute(objects);
}
private object Convert(string value, Type conversionType)
{
//Put your conversion code here to convert the string value into the selected type
}
protected abstract void Execute(object[] objects);
}
This leaves a lot less repetition in your child classes, but it also exposes the number of types in the child class. Executing from your List<ConsoleCommandBase> becomes:
public void Execute(string[] args)
{
List<ConsoleCommandBase> list = GetYourList();
var executer = list.First(c => c.TypeCount == args.Length);
executer.Execute(args);
}
And here is what your child classes might look like:
public class ConsoleCommand<T> : ConsoleCommandBase
{
private readonly Action<T> _action;
public ConsoleCommand(string commandName, Action<T> action) : base(commandName)
{
_action = action;
}
protected override Type[] Types { get; } = new[] { typeof(T) };
protected override void Execute(object[] objects)
{
_action?.Invoke((T)objects[0]);
}
}
public class ConsoleCommand<T1,T2> : ConsoleCommandBase
{
private readonly Action<T1,T2> _action;
public ConsoleCommand(string commandName, Action<T1,T2> action) : base(commandName)
{
_action = action;
}
protected override Type[] Types { get; } = new[] { typeof(T1),typeof(T2) };
protected override void Execute(object[] objects)
{
_action?.Invoke((T1)objects[0],(T2)objects[1]);
}
}

Covariance in generic parameter and convention based on parameter type

I'm really struggling to create interface/convention based rules for FluentValidator. It has following class
abstract class AbstractValidator<T>
{
IRuleBuilderInitial<T, TProperty> RuleFor<TProperty>(Expression<Func<T, TProperty>> expression)
...
}
public interface IWithPropertyA
{
string PropertyA{get;set;}
}
public interface IWithPropertyB
{
string PropertyB{get;set;}
}
public class Handler1Data: IWithPropertyA
{
public string PropertyA {get;set;}
}
public class Handler2Data: IWithPropertyA, IWithPropertyB
{
public string PropertyA {get;set;}
public string PropertyB {get;set;}
}
public class Handler1 : AbstractValidator<Handler1Data> {}
public class Handler2 : AbstractValidator<Handler2Data> {}
I'm trying to create extension method which will basically check if generic argument implements specific interface and then adds rule to it:
public static void ValidateAll<T>(this AbstractValidator<T> validator)
{
(validator as AbstractValidator<IWithPropertyA>)?.RuleFor(x => x.PropertyA).NotEmpty().WithMessage("PropertyA Missing");
(validator as AbstractValidator<IWithPropertyB>)?.RuleFor(x => x.PropertyB).NotEmpty().WithMessage("PropertyB Missing");
}
The problem here is obviously AbstractValidator is not covariant so validator is not castable to neither AbstractValidator<PropertyA> nor AbstractValidator<PropertyB>. I've tried to create my own Base Validator like below and then create extension method based on that but I can't.
public interface IMyValidator<in T>
{
void AddMyRule<TProperty>(Expression<Func<T, TProperty>> expression) //it doesn't work because Expression<Func<T,Property> cannont be covariant
}
public abstract class MyBaseValidator<T>: AbstractValidator<T> ,IMyValidator<T>
{
void AddMyRule<TProperty>(Expression<Func<T, TProperty>> expression)
}
Method will be called in each Handler like this:
public class Handler1 : AbstractValidator<Handler1Data> {
this.ValidateAll();
}
Didn't you mean to write:
(validator as AbstractValidator<IWithPropertyA>)
?.RuleFor(x => x.PropertyA)
.NotEmpty()
.WithMessage("Property1 Missing");
Because Property1 is not defined anywhere.
I found one workaround which avoids using Expression which is obviously the issue here. The downfall of it is that we lose property name and we have to configure message manually.
public interface IMyValidator<out T>
{
void AddMyRule<TProperty>(Func<T, TProperty> expression, string message);
}
public abstract class MyBaseValidator<T> : AbstractValidator<T>, IMyValidator<T>
{
public void AddMyRule<TProperty>(Func<T, TProperty> expression, string message)
{
var exp = FuncToExpression(expression);
RuleFor(exp).NotEmpty().WithMessage(message);
}
private static Expression<Func<T, P>> FuncToExpression<T, P>(Func<T, P> f) => x => f(x);
}
public static class Ext
{
public static void ValidateAll<T>(this AbstractValidator<T> validator)
{
(validator as IMyValidator<IWithPropertyA>)?.AddMyRule(x => x.PropertyA, "PropA Cant be empty");
(validator as IMyValidator<IWithPropertyB>)?.AddMyRule(x => x.PropertyB, "PropB Cant be empty");
}
}
public class Handler1 : MyBaseValidator<Handler1Data>
{
public Handler1()
{
this.ValidateAll();
}
}
public class Handler2 : MyBaseValidator<Handler2Data> { }

Finding out type of a generic class

Lets say I have a generic class:
class Foo {
// protected Type t;
// public void SetT(string strval) {
// ((Foo<t>)this).Set(strval);
// }
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
if (this is Foo<float>) {
this.val = float.Parse(strval);
} else if (this is Foo<int>) {
this.val = int.Parse(strval);
}
}
}
Now I create an object and put it in an ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>);
And then I forget the type of Foo<>. Now, how do I Set? I tried the obvious candidates:
(Foo)a[0].Set("5.0");
(Foo<a[0].GetType()>)a[0].Set("5.0");
but those failed.
Is there a way I can call that Set method without explicitly knowing the type of Foo<>?
If not, can I somehow save type of Foo into Foo.t, and then uncomment and use Foo.SetT?
Ah, generics. Very nice tool if you know how to use them :-)
Regards,
dijxtra
One way is to make your generic Foo class implement an interface:
interface IFoo {
void Set(string strval);
}
class Foo<T> : IFoo {
private T val;
public void Set(string strval) {
...
}
}
Then you can cast to IFoo and call Set():
((IFoo)a[0]).Set("5.0");
There's absolutely no reason to be using generics here. Generics are intended to be used when the type of operations you will be performing are generic. In other words, they are independent of the type(s) on which they are performed. You are doing the opposite: the operation will be different depending on the types.
Given that, you should remove the generic parameter, make Set() and Foo abstract, and derive appropriate classes to handle the different types:
abstract class Foo
{
public abstract void Set(string value);
}
class FooDouble : Foo
{
double val;
public override void Set(string value)
{
this.val = double.Parse(value);
}
}
// Etc.
Then, you should be storing your Foos in a List<T>:
List<Foo> fooList = new List<Foo>();
fooList.Add(new FooDouble());
Later, you can say this:
fooList[0].Set("5.0");
And it will just work! No need to remember!
You want to override the implementation of Set in the derived classes.
class Foo {
public virtual void Set(string val);
}
class Foo<T> : Foo {
public override void Set(string val);
}
In addition to what Jimmy pointed out for your base class, you could use a generic collection instead of an ArrayList and make use of a type converter:
public interface IFoo
{
void Set(string value);
}
public class Foo<T> : IFoo
{
private T val;
public void Set(string value)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if(typeConverter.CanConvertFrom(typeof(string)))
{
val = (T)typeConverter.ConvertFromString(value);
}
else
{
throw new InvalidOperationException();
}
}
}
The above will work with either your ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>());
((IFoo)a[0]).Set("123.4");
Or with a typed collection:
List<IFoo> list = new List<IFoo>();
list.Add(new Foo<float>());
list[0].Set("123.4");
As an added bonus, you don't need to have an if statement in your Set method and try to account for all possible types.
If you want to know the type parameter that was used in you generic, use the GetGenericArguments method.
class Foo<T> {
int input_as_int;
float input_as_float;
public void Set(string strval) {
if (this.GetType().GetGenericArguments().First() == typeof(float)) {
this.input_as_float = float.Parse(strval);
} else if (this.GetType().GetGenericArguments().First() == typeof(int)) {
this.input_as_int = int.Parse(strval);
}
// Else .. throw an exception? return default value? return 0? what makes sense to your application
}
or alternately if you could by pass the Interface entirely and pass the input string in the constructor.
public class Foo<T>
{
public Foo (string input)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter.CanConvertFrom(typeof(string)))
{
Value = (T)typeConverter.ConvertFromString(input);
}
else
{
throw new InvalidOperationException();
}
}
public T Value { get; set;
}
}
then you can just use it like so.
var test = new List<int> Foo ("3");
using System;
using System.Collections;
using System.Collections.Generic;
class Foo {
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
var _type = typeof(T);
val = (T)(_type.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { strval }));
}
override public string ToString(){
return String.Format("{0}", val);
}
}
class Sample {
static void Main(string[] args){
ArrayList a = new ArrayList();
a.Add(new Foo<float>());
a.Add(new Foo<int>());
dynamic ax = a[0];
ax.Set("5.5");
ax = a[1];
ax.Set("55");
//EDIT
//But I may have to set the float value to Foo <int> If you forgot
// ((Foo<float>)a[0]).Set("5.5");
// ((Foo<int>)a[1]).Set("55");
Console.WriteLine("{0},{1}", a[0], a[1]);
}
}

Duck Typing DynamicObject derivate

I wrote a class that allows a derivate to specify which of its properties can be lazy loaded. The code is:
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
And a derivate class:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address", () => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
This works perfectly fine for getting and settings property values, but I get a either a RuntimeBinderException when I implicitly cast or an InvalidCastException with an explicitly cast SelfHydratingEntity back to T.
I know that you can override the DynamicObject.TryConvert method, but I'm wondering what exactly to put in this method. I've read a lot about duck typing today, and have tried out several libraries, but none of them work for this particular scenario. All of the libraries I've tried today generate a wrapper class using Reflection.Emit that makes calls to "get_" and "set_" methods and naturally use reflection to find these methods on the wrapped instance. SelfHydratingEntity of course doesn't have the "get_" and "set_" methods defined.
So, I'm wondering if this kind of thing is even possible. Is there any way to cast an instance of SelfHydratingEntity to T? I'm looking for something like this:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
Have you seen this Duck Typing project. It looks pretty good. I have just found a great example from Mauricio. It uses the Windsor Castle dynamic proxy to intercept method calls
Using the code from Mauricio the following code works like a dream
class Program
{
static void Main(string[] args)
{
dynamic person = new { Name = "Peter" };
var p = DuckType.As<IPerson>(person);
Console.WriteLine(p.Name);
}
}
public interface IPerson
{
string Name { get; set; }
}
public static class DuckType
{
private static readonly ProxyGenerator generator = new ProxyGenerator();
public static T As<T>(object o)
{
return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
}
}
public class DuckTypingInterceptor : IInterceptor
{
private readonly object target;
public DuckTypingInterceptor(object target)
{
this.target = target;
}
public void Intercept(IInvocation invocation)
{
var methods = target.GetType().GetMethods()
.Where(m => m.Name == invocation.Method.Name)
.Where(m => m.GetParameters().Length == invocation.Arguments.Length)
.ToList();
if (methods.Count > 1)
throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
if (methods.Count == 0)
throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
var method = methods[0];
if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
method = method.MakeGenericMethod(invocation.GenericArguments);
invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
}
}
impromptu-interface
https://github.com/ekonbenefits/impromptu-interface
Can static cast interfaces onto objects derived from DynamicObject.

Constraint parameters, new()

Is there any way to move the Parse method into the abstract class ? I tried multiple ways (links at the bottom), but I am still hitting one or another roadblock.
public class AnimalEntityId : EntityId<AnimalEntityId>
{
public AnimalEntityId()
: base()
{
}
private AnimalEntityId(string value)
: base(value)
{
}
public static AnimalEntityId Parse(string value)
{
return new AnimalEntityId(value);
}
}
public abstract class EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
}
Tried these suggestions with no luck:
Passing arguments to C# generic new() of templated type
Is there a generic constructor with parameter constraint in C#?
https://social.msdn.microsoft.com/Forums/en-US/fd43d184-0503-4d4a-850c-999ca58e1444/creating-generic-t-with-new-constraint-that-has-parameters?forum=csharplanguage
http://www.gamedev.net/topic/577668-c-new-constraint--is-it-possible-to-add-parameters/
Thanks in advance!
If you don't mind using reflection, you can move Parse into the abstract type like this:
public static TEntityId Parse(string val) {
var constr = typeof(TEntityId).GetConstructor(
// Since the constructor is private, you need binding flags
BindingFlags.Instance | BindingFlags.NonPublic
, null
, new[]{ typeof(string) }
, null);
if (constr == null) {
throw new InvalidOperationException("No constructor");
}
return (TEntityId)constr.Invoke(new object[] {val});
}
Demo.
No, you cannot write a template constraint such as new(string) instead of simply new(). You'll have to leverage reflection to get it to work:
public abstract class EntityId<TEntityId>
where TEntityId : EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
public static TEntityId Parse(string value)
{
return (TEntityId)Activator.CreateInstance(typeof(TEntityId), new object[] { value });
}
}
Assuming you make the constructor accessible (instead of it currently being private). Note the constraint where TEntityId : EntityId<TEntityId> - which will ensure we'll only return subclasses of EntityId
How about making value a private mutable field/property and actually setting it from the Parse method?
(Curiously recurring generic parameter removed from EntityId for simplicity)
public class SimpleAnimalEntityId : EntityId
{
// Implicit parameterless constructor.
}
public class ParametrizedAnimalEntityId : EntityId
{
// Parametrized constructor only.
public ParametrizedAnimalEntityId(int ignored)
{
}
}
public abstract class EntityId
{
// Simple scenario: derived type has a parameterless constructor.
public static TEntity Parse<TEntity>(string value)
where TEntity : EntityId, new()
{
Guid id = Guid.Parse(value);
return new TEntity { value = id };
}
// Advanced scenario: derived type constructor needs parameters injected.
public static TEntity Parse<TEntity>(string value, Func<TEntity> constructor)
where TEntity : EntityId
{
Guid id = Guid.Parse(value);
TEntity entity = constructor();
entity.value = id;
return entity;
}
private Guid value;
protected EntityId()
{
value = Guid.NewGuid();
}
}
Now you can handle any constructor from your Parse method:
string id = Guid.NewGuid().ToString();
SimpleAnimalEntityId simple = EntityId.Parse<SimpleAnimalEntityId>(id);
ParametrizedAnimalEntityId parametrized = EntityId.Parse(id, () => new ParametrizedAnimalEntityId(42));

Categories