Inheritance Generic Invariance C#4 - c#-4.0

I've been searching why this generic contruction doesn't compile
I get:
Cannot implicitly convert type 'WpfApplication1.CowDao' to 'WpfApplication1.Dao'
public abstract class Animal { }
public class Dog : Animal { }
public class Cow : Animal { }
public abstract class Dao<T> where T : Animal
{
public void Insert(T t);
}
public class DogDao : Dao<Dog> { }
public class CowDao : Dao<Cow> { }
public class Main
{
public Main()
{
Dao<Animal> dao = null;
if (true) dao = new DogDao();
else dao = new CowDao();
}
}
I just want to get to my goal --> making a 'neutral' instance
I think that my construction has to change, but i don't know how
I'm using .NET Framework 4
Thanks

Generics from a derived does not inherit from Generic from a base class so you may not cast one to another. Instead, write an extension method ToGenericParent that converts like that:
public static Generic<Parent> ToGenericParent(this Generic<Derived> derived)
{
return new Generic<Parent>() { Value = derived.Value };
}

Change your Inheritance for your Dao layers as
public class DogDao : Dao<Animal> { }
public class CowDao : Dao<Animal> { }
Edit:
public abstract class Dao<T> where T : Animal
{
public virtual void Insert(T t)
{
}
protected void ExecuteQuery(string quer)
{
}
}
public class DogDao : Dao<Dog>
{
public override void Insert(Dog t)
{
string insert = "INSERT INTO DOG ...";
base.ExecuteQuery(insert);
}
}
public class CowDao : Dao<Cow>
{
public override void Insert(Cow t)
{
string insert = "INSERT INTO COW ...";
base.ExecuteQuery(insert);
}
}

Related

Expression mapping using Automapper throws a System.EntryPointNotFoundException after migrating to Automapper 10

I am using automapper to map expressions between classes that implement IEnumerable. The base classes look like this:
public abstract class EntityDtoBase<T> : DtoBase<T> where T : EntityDtoBase<T>
{
public virtual int Id { get; set; }
}
public abstract class PersistenceDtoBase<T> : DtoBase<T> where T : PersistenceDtoBase<T>
{
public virtual int Id { get; set; }
}
public abstract class DtoBase<T> : IEnumerable<T> where T : DtoBase<T>
{
private readonly IList<T> _items;
public int Count => _items.Count;
protected DtoBase()
{
this._items = new List<T>();
}
public void Add(T item)
{
_items.Add(item);
}
/* other methods like AddRange... */
IEnumerator IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return _items.GetEnumerator();
}
}
After migrating to Automapper 10, expression mapping between classes enheriting from EntityDtoBase and PersistenceDtoBase throws a System.EntryPointNotFoundException : Entry point was not found. The configuration I am using in my project is similar to the one used in this unit test:
public class UserEntityDto : EntityDtoBase<UserEntityDto> { }
public class UserPersistenceDto : PersistenceDtoBase<UserPersistenceDto> { }
public class UserProfile : Profile
{
public UserProfile() { CreateMap<UserEntityDto, UserPersistenceDto>().ReverseMap(); }
}
public class UnitTest
{
private readonly IMapper _mapper;
public UnitTest()
{
var sp = CreateServices();
_mapper = sp.GetRequiredService<IMapper>();
}
private static IServiceProvider CreateServices()
{
return new ServiceCollection()
.AddAutoMapper(cfg =>
{
cfg.AddExpressionMapping();
cfg.AddCollectionMappers();
cfg.ForAllMaps((map, exp) => exp.MaxDepth(1));
cfg.AllowNullCollections = true;
cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
}, typeof(UnitTest).Assembly)
.BuildServiceProvider(false);
}
[Fact]
public void Should_Map_Expression()
{
Expression<Func<UserEntityDto, bool>> searchExpression = u => u.Id == 1;
var searchExpressionMapped = _mapper.Map<Expression<Func<UserPersistenceDto, bool>>>(searchExpression);
Assert.NotNull(searchExpressionMapped);
}
You can find the complete unit test project here. The test succeeds using Automapper 9 and fails using Automapper 10.

ArrayList with Objects which implements an Interface

I want a ArrayList, where you can add Objects , which implements an Interface.
Something like this:
ArrayList<Object implements Interface> list =
new ArrayList<Object which implements a specific Interface>();
What is the correct syntax for this?
Just set the interface as the type of the generic. Here you go the code in C#:
interface IFoo {
void foo();
}
class Foo1 : IFoo {
public void foo() {
Console.WriteLine("foo1");
}
}
class Foo2 : IFoo {
public void foo() {
Console.WriteLine("foo2");
}
}
class Program {
public static void Main() {
// IFoo type: any object implementing IFoo may go in
List<IFoo> list = new List<IFoo>();
list.Add(new Foo1());
list.Add(new Foo2());
foreach(IFoo obj in list) obj.foo(); // foo1, foo2
Console.ReadKey();
}
}

AutoMapper.."CreateMapExpression" doesn't support to create map for Linq.Expression for "Enum" type which from different namespace

Based on my test for mapping Linq.Expression using Automapper, it's not support to use "Enum" which in different namespaces.
Please see my sample below,
namespace TestNamespace1
{
public enum EnumTypes
{
EnumType01,
EnumType02
}
}
namespace TestNamespace2
{
public enum EnumTypes
{
EnumType01,
EnumType02
}
}
namespace MappingTest
{
class A
{
public TestNamespace1.EnumTypes EnumType { get; set; }
}
class B
{
public TestNamespace2.EnumTypes EnumType { get; set; }
}
class TestMapping
{
static void Main()
{
var bDataSource = new List<B> { new B { EnumType = **TestNamespace2**.EnumTypes.EnumType01 } };
Mapper.CreateMap<A, B>();
Mapper.CreateMap<B, A>();
Expression<Func<A, bool>> expressionA = x => x.EnumType == TestNamespace1.EnumTypes.EnumType01;
var expressionB = GetMappedSelectorForAB(expressionA);
var result = bDataSource.AsQueryable().Where(expressionB);
foreach (B b in result)
{
Console.WriteLine("Matching B: {0}", b.EnumType.ToString());
}
}
static Expression<Func<B, bool>> GetMappedSelectorForAB(Expression<Func<A, bool>> selector)
{
Expression<Func<B, A>> mapper = AutoMapper.QueryableExtensions.Extensions.CreateMapExpression<B, A>(Mapper.Engine);
Expression<Func<B, bool>> mappedSelector = selector.Compose(mapper);
return mappedSelector;
}
}
public static class FunctionCompositionExtensions
{
public static Expression<Func<X, Y>> Compose<X, Y, Z>(this Expression<Func<Z, Y>> outer, Expression<Func<X, Z>> inner)
{
return Expression.Lambda<Func<X, Y>>(
ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
inner.Parameters[0]);
}
}
class ParameterReplacer : ExpressionVisitor
{
private ParameterExpression _parameter;
private Expression _replacement;
private ParameterReplacer(ParameterExpression parameter, Expression replacement)
{
_parameter = parameter;
_replacement = replacement;
}
public static Expression Replace(Expression expression, ParameterExpression parameter, Expression replacement)
{
return new ParameterReplacer(parameter, replacement).Visit(expression);
}
protected override Expression VisitParameter(ParameterExpression parameter)
{
if (parameter == _parameter)
{
return _replacement;
}
return base.VisitParameter(parameter);
}
}
}
AutoMapper.QueryableExtensions.Extensions.CreateMapExpression
I have saw the source code of Automapper, and debuged it I will got this error "Unable to create a map expression from ..."
If both of the Class A and B use the same Enum from same namespace, then it works fine like this
class A
{
public TestNamespace1.EnumTypes EnumType { get; set; }
}
class B
{
public TestNamespace1.EnumTypes EnumType { get; set; }
}
Is there a way to implement it? we know the target and source object may have themselft namespace [DTO].

generic delete does not work?

I have this abstract repository class with a Delete method:
public abstract class MyRepository<C, T> :
IMyRepository<T>
where T : class
where C : ObjectContext, new()
{
private C _entities = new C();
public C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual void Delete(T entity)
{
_entities.Attach(entity);
_entities.DeleteObject(entity);
_entities.SaveChanges();
}
}
however this does not compile? how can I Create a generic delete method here?
Instead of this
private C _entities = new C();
Use Activator.CreateInstance:
private C _entities = Activator.CreateInstance<T>();
Modify your Delete method as follows
public virtual void Delete(T entity)
{
_entities.CreateObjectSet<T>().Attach(entity);
_entities.DeleteObject(entity);
_entities.SaveChanges();
}
public virtual void Update(T entity)
{
_entities.CreateObjectSet<T>().Attach(entity);
_entities.ObjectStateManager
.ChangeObjectState(entity, System.Data.EntityState.Modified);
_entities.SaveChanges();
}

How to define a constraint on class type if It has custom attribute?

there is any way to force a class to implement an interface , if It has an specific custom attribute?
I want to have a compile time error , if the class with specific attribute does not implement an specific interface.
[myAttrib]
public MyClass:IMyInterface
{
}
If myClass is not typeof(IMyInterface) , I will get an error in compile time.
thanks,
In case of properties, You could create an abstract class inheriting the interface and gets your final class drive from that abstract class.
Have a look at
public interface Test
{
string Name { get; set; }
}
public abstract class Test1 : Test
{
public abstract string Name { get; set; }
}
public class Test2 : Test1
{
}
For custom attribute you could do
public class Alias : System.Attribute
{
string[] _types;
public Alias(params string[] types)
{
this.Types = types;
}
public Alias()
{
this.Types = null;
}
public string[] Types
{
get { return _types; }
set { _types = value; }
}
}
public interface Test
{
Alias Attrib{ get;}
}
public abstract class Test1 : Test
{
public abstract Alias Attrib { get; }
}
public class Test2 : Test1
{
}
Hope I answer your question.

Resources