C# Inheritance with Generics and the dynamic keyword - c#

The problem I'm actually working on is related to mappers in ASP.NET MVC but that's way too complex to post on SO, so I've simplified the issue I'm having below. I'll post my code first as it's easier to explain what I'm trying to achieve after the code.
Supporting Code
public abstract class BaseFoo
{
public int CommonProperty { get; set; }
}
public class Foo1 : BaseFoo
{
public int SomeProperty { get; set; }
}
public class Foo2 : BaseFoo
{
public int AnotherProperty { get; set; }
}
public interface IMyInterface<T>
{
void SomeMethod(T t);
}
public abstract class BaseClass<T> : IMyInterface<T>
where T : BaseFoo
{
public virtual void SomeMethod(T t)
{
t.CommonProperty = 1;
}
}
public class ConcreteClass1 : BaseClass<Foo1>
{
public override void SomeMethod(Foo1 t)
{
t.SomeProperty = 57;
base.SomeMethod(t);
}
}
public class ConcreteClass2 : BaseClass<Foo2>
{
public override void SomeMethod(Foo2 t)
{
t.AnotherProperty = 123;
base.SomeMethod(t);
}
}
public static class ConcreteClassFactory
{
public enum ConcreteClassType
{
ConcreteClass1,
ConcreteClass2
}
public static dynamic CreateClass(ConcreteClassType type)
{
dynamic toReturn = null;
switch (type)
{
case ConcreteClassType.ConcreteClass1:
toReturn = new ConcreteClass1();
break;
case ConcreteClassType.ConcreteClass2:
toReturn = new ConcreteClass2();
break;
default:
break;
}
return toReturn;
}
}
What I want to do is dynamically create different ConcreteClasss and call SomeMethod on that created object, basically I want to pass around my ConcreteClasss as BaseClass, much like you can pass around Foos as BaseFoo. I've gotten it to work with the following code:
class Program
{
static void Main(string[] args)
{
BaseFoo foo = new Foo1();
dynamic bar = ConcreteClassFactory.CreateClass(ConcreteClassFactory.ConcreteClassType.ConcreteClass1);
bar.SomeMethod(foo as dynamic);
}
}
However, this seems very kludgy to cast to a dynamic (also I don't fully understand why removing as dynamic throws a RuntimeBinderException, if someone can explain what's going on that would be appreciated). Is there a better way to achieve what I'm trying to do here?

With the constraints you have what I would do would be to cast and throw errors from inside the overridden SomeMethod.
public abstract class BaseClass : IMyInterface<BaseFoo>
{
public virtual void SomeMethod(BaseFoo t)
{
t.CommonProperty = 1;
}
}
public class ConcreteClass1 : BaseClass
{
public override void SomeMethod(BaseFoo t)
{
if(t == null)
throw new ArgumentNullException(nameof(t));
var foo1 = t as Foo1;
if(foo1 == null)
throw new NotSupportedException($"{nameof(ConcreteClass1)} does not support types other than {nameof(Foo1)}");
foo1.SomeProperty = 57;
base.SomeMethod(foo1);
}
}
public class ConcreteClass2 : BaseClass
{
public override void SomeMethod(BaseFoo t)
{
if (t == null)
throw new ArgumentNullException(nameof(t));
var foo2 = t as Foo2;
if (foo2 == null)
throw new NotSupportedException($"{nameof(ConcreteClass2)} does not support types other than {nameof(Foo2)}");
foo2.AnotherProperty = 123;
base.SomeMethod(foo2);
}
}
public static class ConcreteClassFactory
{
public enum ConcreteClassType
{
ConcreteClass1,
ConcreteClass2
}
public static BaseClass CreateClass(ConcreteClassType type)
{
BaseClass toReturn = null;
switch (type)
{
case ConcreteClassType.ConcreteClass1:
toReturn = new ConcreteClass1();
break;
case ConcreteClassType.ConcreteClass2:
toReturn = new ConcreteClass2();
break;
default:
break;
}
return toReturn;
}
}
Used like
class Program
{
static void Main(string[] args)
{
BaseFoo foo = new Foo1();
var bar = ConcreteClassFactory.CreateClass(ConcreteClassFactory.ConcreteClassType.ConcreteClass1);
bar.SomeMethod(foo);
}
}

Related

Casting from concrete Type to interface

I have following code that does not compile
using System.Collections.Generic;
public interface IElement
{
}
public class AElement : IElement
{
public void DoSomethingSpecial()
{ }
}
public class Container<TElement>
{
public List<TElement> Elements { get; } = new();
}
public class Program
{
public static Container<IElement> GetContainer()
{
var concreteContainer = new Container<AElement>();
concreteContainer.Elements.ForEach(e => e.DoSomethingSpecial());
return concreteContainer; // Cannot implicitly convert type 'Container<AElement>' to 'Container<IElement>'
}
public static void Main()
{
var myContainer = GetContainer();
}
}
I read documentation about Covariance, Invariance, Contravariance and out Types.
And I am more confused than at the beginning.
Whats the way to fix this?
Code online: https://dotnetfiddle.net/85AgfT
You need to generate implicit conversion operator:
public class Container<IElement>
{
public List<IElement> Elements { get; } = new List<IElement>();
public static implicit operator Container<IElement>(Container<AElement> v)
{
//here you need to create Container<IElement> with your Container<AElement> 'v' values
return new Container<IElement>();
}
}
I finally got it working
using System.Collections.Generic;
public interface IContainer<out TElement>
{
}
public interface IElement
{
}
public class AElement : IElement
{
public void DoSomethingSpecial()
{ }
}
public class Container<TElement> : IContainer<TElement>
{
public List<TElement> Elements { get; } = new();
}
public class Program
{
public static IContainer<IElement> GetContainer()
{
var concreteContainer = new Container<AElement>();
concreteContainer.Elements.ForEach(e => e.DoSomethingSpecial());
return concreteContainer;
}
public static void Main()
{
var myContainer = GetContainer();
}
}
Make Container also an Interface and use an out Type parameter

c# Get if property type inherits from one abstract generic class with reflection

I would like to get all of the properties contained in a class whose types inherit from a certain abstract and generic class.
public abstract class foo<T> { }
public class fooInt_Indexed : foo<int> { }
public class fooInt_Not_Indexed : foo<int> { }
public class fooString_Compressed : foo<string> { }
public class fooString_Indexed : foo<string> { }
public class fooFloat : foo<float> { }
public abstract class bar
{
}
public class foobar : bar
{
public fooInt_Indexed value { get; set; }
public fooInt_Not_Indexed someOtherValue { get; set; }
public fooFloat someFloat { get; set; }
public otherData<int> {get; set; }
}
public class barChecker<T> where T : bar
{
public List<PropertyInfo> fooprops = new List<PropertyInfo>();
public static barChecker<T> Generator()
{
var #new = new barChecker<T>();
foreach (var item in typeof(T).GetProperties())
{
if (item.PropertyType is somesortof(foo<>)) #new.fooprops.Add(item);
}
return #new;
}
What do I need to put inside the barChecker<T> class code to make its fooprops list contain the property infos of "value","someOtherValue" and "someFloat" when generated as a barChecker<foobar> ?
Here's an extension method to System.Type that will answer this and similar questions about inheritance:
public static class TypeExtensions
{
public static bool InheritsFrom(this Type t, Type baseType)
{
if (t.BaseType == null)
{
return false;
}
else if (t == baseType)
{
return true;
}
else if (t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition().InheritsFrom(baseType))
{
return true;
}
else if (t.BaseType.InheritsFrom(baseType))
{
return true;
}
return false;
}
public static bool InheritsFrom<TBaseType>(this Type t)
=> t.InheritsFrom(typeof(TBaseType));
}
This here:
item.PropertyType is somesortof(foo<>)
Has to be replaced with
typeof(YourType).IsAssignableFrom(item.PropertyType)
The 'is' operator is only for real object instances, not if you already have a Type-Reference.
So in your case 'YourType' is typeof(barchecker< foobar >) ?

Explicit use of base method without using keyword new in child method

Due to the polymorphism property of the classes, below example will print AB twice, which is expected.
In my case, I really want it to print A then AB.
I decided to change the Get() method in B from overrides to new.
This solves my problem, but they informed me of bad practise, so I'm looking for an alternative...
The one thing that comes to mind is to instantiate a new A in B.Do(), which I think is also bad practise...
//ORIGINAL
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Do();
}
}
public class A
{
public virtual void Do()
{
var get = Get();
Console.WriteLine(get);
}
public virtual string Get()
{
return "A";
}
}
public class B : A
{
public override void Do()
{
base.Do();
var get = Get();
Console.WriteLine(get);
}
public override string Get()
{
return base.Get() + "B";
}
}
//UPDATED, USING NEW
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Do();
Console.ReadLine();
}
}
public class A
{
public virtual void Do()
{
var get = Get();
Console.WriteLine(get);
}
public virtual string Get()
{
return "A";
}
}
public class B : A
{
public override void Do()
{
base.Do();
var get = Get();
Console.WriteLine(get);
}
public new string Get()
{
return base.Get() + "B";
}
}
Instead of calling the base version of Do in B.Do, you can change the implementation as follows:
public class B : A
{
public override void Do()
{
// Call the base version of Get explicitly
var getBase = base.Get();
Console.WriteLine(getBase);
// Call the current implementation of Get
var get = Get();
Console.WriteLine(get);
}
public override string Get()
{
return "B";
}
}
This will technically solve your problem, but is not a really clean solution from an OOP point of view. I suggest to think a bit about whether you need to be able to override Get independently. Maybe changing the signatures of your methods so that Get always returns a list of strings that should be printed is also a good solution (I've renamed Get to GetLines to reflect the changed purpose of the method):
public class A
{
public virtual void Do()
{
var lines = GetLines();
foreach(var line in lines)
Console.WriteLine(line);
}
public virtual IEnumerable<string> GetLines()
{
return new string[] { "A" };
}
}
public class B : A
{
public override IEnumerable<string> GetLines()
{
var lst = new List<string>(base.GetLines());
lst.Add("B");
return lst;
}
}
Here is the corrected code:
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Do();
}
}
public class A
{
public virtual void Do()
{
Console.WriteLine(Get());
}
public virtual string Get()
{
return "A";
}
}
public class B : A
{
public override void Do()
{
Console.WriteLine(base.Get());
base.Do();
}
public override string Get()
{
return base.Get() + "B";
}
}

Cannot convert from 'SpecificComponent' to 'IComponent<IComponentGuid>'

I've this class structure:
namespace ClassLibrary1
{
public interface IComponentGuid { }
class ComponentGuid : IComponentGuid{}
internal interface IComponent<T> where T : IComponentGuid {
List<T> List();
}
class SpecificComponent : IComponent<ComponentGuid> {
public List<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
}
class P
{
public P(IComponent<IComponentGuid> pComponent) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}
The problem arise instantiating P: var p = new P(specific);
I get a
cannot convert from 'ClassLibrary1.SpecificComponent' to 'ClassLibrary1.IComponent<ClassLibrary1.IComponentGuid>'
What am I doing wrong?
Thank you.
You can make it work if you forgo List<T> on your interface and replace it with a co-variant interface of IEnumerable<T> and then make your type parameter co-variant as well:
namespace ClassLibrary1
{
public interface IComponentGuid { }
class ComponentGuid : IComponentGuid{}
internal interface IComponent<out T> where T : IComponentGuid {
IEnumerable<T> List();
}
class SpecificComponent : IComponent<ComponentGuid> {
public IEnumerable<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
}
class P
{
public P(IComponent<IComponentGuid> pComponent) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}
I'm trying this solution splitting the IComponent interface into two, one covariant and one invariant.
namespace ClassLibrary1
{
public interface IComponentGuid { }
public class ComponentGuid : IComponentGuid { }
public interface IComponentBase<out T> where T : IComponentGuid
{
IEnumerable<T> List();
}
interface IComponent<T>
{
void AddToList(T item );
}
public class SpecificComponent : IComponentBase<ComponentGuid>, IComponent<ComponentGuid>
{
public IEnumerable<ComponentGuid> List()
{
throw new System.NotImplementedException();
}
public void AddToList(ComponentGuid item)
{
throw new System.NotImplementedException();
}
}
public class P
{
public P(IComponentBase<IComponentGuid> pComponentBase) { }
}
class Caller
{
public Caller()
{
var specific = new SpecificComponent();
var p = new P(specific);
}
}
}

Making Validation Generic

I have the following C# code. Here the validations are kept outside the class to satisfy Open – Closed Principle. This is working fine. But the challenge is – the validations are not generic. It is specific to employee class (E.g DateOfBirthRuleForEmployee). How do I make the validations generic for all objects (DateOfBirthRuleForAnyObject).
Note: Make Generic <==> Make Type-Independent
Note: I have NameLengthRuleForEmployee validation also. New validation may come in future.
EDIT
Generic Method Example: Using “OfType” in LINQ
CODE
class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
employee.DateOfBirth = DateTime.Now;
employee.Name = "Lijo";
DateOfBirthRuleForEmployee dobRule = new
DateOfBirthRuleForEmployee();
NameLengthRuleForEmployee nameRule = new
NameLengthRuleForEmployee();
EmployeeManager employeeManager = new EmployeeManager();
employeeManager.AddRules(dobRule);
employeeManager.AddRules(nameRule);
bool result = employeeManager.validateEntity(employee);
Console.WriteLine(result);
Console.ReadLine();
}
}
public interface IEntity
{
}
public interface IRule<TEntity>
{
bool IsValid(TEntity entity);
}
public class DateOfBirthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee entity)
{
return (entity.DateOfBirth.Year <= 1975);
}
}
public class NameLengthRuleForEmployee : IRule<Employee>
{
public bool IsValid(Employee employee)
{
return (employee.Name.Length < 5);
}
}
public class Employee : IEntity
{
private DateTime dateOfBirth;
private string name;
public DateTime DateOfBirth
{
get
{
return dateOfBirth;
}
set
{
dateOfBirth = value;
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
public class EmployeeManager
{
RulesEngine<Employee> engine = new RulesEngine<Employee>();
public void AddRules(IRule<Employee> rule)
{
engine.AddRules(rule);
//engine.AddRules(new NameLengthRuleForEmployee());
}
public bool validateEntity(Employee employee)
{
List<IRule<Employee>> rulesList = engine.GetRulesList();
//No need for type checking. Overcame Invariance problem
bool status = true;
foreach (IRule<Employee> theRule in rulesList)
{
if (!theRule.IsValid(employee))
{
status = false;
break;
}
}
return status;
}
}
public class RulesEngine<TEntity> where TEntity : IEntity
{
private List<IRule<TEntity>> ruleList = new
List<IRule<TEntity>>();
public void AddRules(IRule<TEntity> rule)
{
//invariance is the key term
ruleList.Add(rule);
}
public List<IRule<TEntity>> GetRulesList()
{
return ruleList;
}
}
The challange is for your rules to know which property of what type to validate. You can either provide this by implementing an interface that provides just that as suggested by SLaks or by quessing it dynamically or by providing a concrete rule class with a bit more information on how to access the given property, e.g.:
class NameRule<T> : IRule<T>
{
private Func<T, string> _nameAccessor;
public NameRule(Func<T, string> nameAccessor)
{
_nameAccessor = nameAccessor;
}
public bool IsValid(T instance)
{
return _nameAccessor(instance).Length > 10;
}
}
this ofcourse can be used in the following way:
NameRule<Employee> employeeNameRule = new NameRule<Employee>(x => x.name);
employeeManager.addRule(employeeNameRule);

Categories

Resources