I'm using a ViewModelBuilder-class to map my models to ViewModels.
Problem is, when I try to build viewmodels for the Projects property I use a viewmodelbuilder for that too and THAT viewmodelbuilder's model has a reference back to Account which it will also try to map to a viewmodel. Result is stackoverflowexeption.
How to solve this?
I thought of sending a bool to the mapping functions, but then I will lose mapping of some nested properties that i do want to map.
Very thankful for any advice I could get!
public class AccountViewModelBuilder : IViewModelBuilder<AccountViewModel, Account>
{
protected AllViewModelBuilders _allViewModelBuilders { get; private set; }
public AccountViewModelBuilder(AllViewModelBuilders allViewModelBuilders)
{
_allViewModelBuilders = allViewModelBuilders;
}
public AccountViewModel BuildFromEntity(Account entity)
{
return new AccountViewModel()
{
ID = entity.ID,
Name = entity.Name,
//Projects = _allViewModelBuilders.ProjectViewModelBuilder.BuildFromEntity(entity.Projects).ToList()
};
}
public Account BuildFromViewModel(AccountViewModel viewModel, Account entity)
{
if (entity == null) return null;
entity.Name = viewModel.Name;
//entity.Projects = _allViewModelBuilders.ProjectViewModelBuilder.BuildFromViewModel(viewModel.Projects).ToList();
return entity;
}
public IEnumerable<AccountViewModel> BuildFromEntity(ICollection<Account> entities)
{
foreach (var entity in entities)
yield return BuildFromEntity(entity);
}
public IEnumerable<Account> BuildFromViewModel(ICollection<AccountViewModel> viewModels)
{
throw new NotImplementedException();
}
}
Edit
So i decided to go with AutoMapper, with some extensions...
public static class ConditionExtensions
{
public static void IgnoreIfSourceIsNull<T>(this IMemberConfigurationExpression<T> expression)
{
expression.Condition(IgnoreIfSourceIsNull);
}
static bool IgnoreIfSourceIsNull(ResolutionContext context)
{
if (!context.IsSourceValueNull)
{
return true;
}
var result = context.GetContextPropertyMap().ResolveValue(context.Parent);
return result.Value != null;
}
}
public static class AutoMapperConfig
{
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
&& x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
public static void Configure()
{
Mapper.CreateMap<Project, ProjectViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<ProjectViewModel, Project>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<LogbookUser, RegisterViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<RegisterViewModel, LogbookUser>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<Account, AccountViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<AccountViewModel, Account>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<FileGroup, FileGroupViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<FileGroupViewModel, FileGroup>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<AttachedFile, AttachedFileViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<AttachedFileViewModel, AttachedFile>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<Customer, CustomerViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<CustomerViewModel, Customer>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
Mapper.CreateMap<WorkOrder, WorkOrderViewModel>().IgnoreAllNonExisting();
Mapper.CreateMap<WorkOrderViewModel, WorkOrder>().IgnoreAllNonExisting().ForAllMembers(c => c.IgnoreIfSourceIsNull());
}
}
Related
How could I make following concise, with an extension method etc.? Also could that InlineValidator consolidated into the MainPropertyValidator class?
public class PropertyDTOValidator : AbstractValidator<PropertyDTO>
{
public PropertyDTOValidator()
{
RuleFor(p => p).SetValidator(new InlineValidator<PropertyDTO>
{
validator =>
{
return validator.RuleFor(p => p.MainProperty)
.SetValidator(new MainPropertyValidator());
}
}).When(p =>
{
var checkMainProperty = p.MainProperty.Id != -1;
if (!checkMainProperty)
{
// Some actions...
}
return checkMainProperty;
});
}
class MainPropertyValidator : AbstractValidator<PropertyDTO>
{
public MainPropertyValidator()
{
RuleFor(p => p.Id).Must(id =>
{
return id >= 1;
}).WithMessage("MainProperty Id value is not valid...");
}
}
}
Edit
I have following extension but i want to consolidate my validator into a single class like InlineValidator. I checked the code of InlineValidator but i could not consolidate InlineValidator and MainPropertyValidator.
public static class Extensions
{
public static IRuleBuilderOptions<T, TProperty1> SetValidator<T, TProperty1, TProperty2>(this IRuleBuilderInitial<T, TProperty1> ruleBuilder,
Expression<Func<T, TProperty2>> exp, IValidator<TProperty2> validator)
{
return ruleBuilder.SetValidator(new InlineValidator<T>
{
v => v.RuleFor(exp).SetValidator(validator)
} as IValidator<TProperty1>);
}
}
RuleFor(p => p).SetValidator(p => p.MainProperty, new MainPropertyValidator()).When(p =>{});
Alternatively, following extensions could be used;
public static class Extensions
{
public static IRuleBuilderInitial<T, TProperty> When<T, TProperty>(this IRuleBuilderInitial<T, TProperty> rule, Func<T, bool> predicate, ApplyConditionTo applyConditionTo = ApplyConditionTo.AllValidators)
{
return rule.Configure(config =>
{
PropertyRule propertyRule = config;
int num = (int)applyConditionTo;
propertyRule.ApplyCondition(ctx => predicate((T)ctx.InstanceToValidate), (ApplyConditionTo)num);
});
}
public static IRuleBuilderInitial<T, TProperty> Custom<T, TProperty, TProperty2>(this IRuleBuilder<T, TProperty> ruleBuilder, Expression<Func<TProperty, TProperty2>> expression, AbstractValidator<TProperty2> validator)
{
var propChain = PropertyChain.FromExpression(expression);
var propName = propChain.ToString();
var prop = expression.Compile();
Func<string, string, string> joinStr = (s1, s2) => string.Join(".", new[] { s1, s2 }.Where(s => !string.IsNullOrEmpty(s)));
return ruleBuilder.Custom((p, context) =>
{
var val = prop(p);
var validationResult = validator.Validate(val);
propName = joinStr(context.PropertyName, propName);
foreach (var failure in validationResult.Errors)
{
failure.PropertyName = joinStr(propName, failure.PropertyName);
context.AddFailure(failure);
}
});
}
}
RuleFor(p => p).Custom(p => p.MainProperty, new MainPropertyValidator()).When(p =>
{
var checkMainProperty = p.MainProperty.Id != -1;
if (!checkMainProperty)
{
// Some actions...
}
return checkMainProperty;
});
I have a scneario in which I want to use reflection to do validation using FluentValidation. Someting like this:
public class FooValidator : AbstractValidator<Foo>
{
public FooValidator(Foo obj)
{
// Iterate properties using reflection
var properties = ReflectionHelper.GetShallowPropertiesInfo(obj);
foreach (var prop in properties)
{
// Create rule for each property, based on some data coming from other service...
//RuleFor(o => o.Description).NotEmpty().When(o => // this works fine when foo.Description is null
RuleFor(o => o.GetType().GetProperty(prop.Name)).NotEmpty().When(o =>
{
return true; // do other stuff...
});
}
}
}
The call to ReflectionHelper.GetShallowPropertiesInfo(obj) returns "shallow" properties of object. Then, for each property I create a rule.
This is my code for get properties of object:
public static class ReflectionHelper
{
public static IEnumerable<PropertyInfo> GetShallowPropertiesInfo<T>(T o) where T : class
{
var type = typeof(T);
var properties =
from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
where pi.PropertyType.Module.ScopeName == "CommonLanguageRuntimeLibrary"
&& !(pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
select pi;
return properties;
}
}
This code compile and can be executed
IValidator<Foo> validator = new FooValidator(foo);
var results = validator.Validate(foo);
But it doesn't work properly (validation never fails). Is there any way to achieve this?
Note: Demo code can be found int Github at FluentValidationReflection
Finally I've found a solution that works. I've created a custom PropertyValidator that receives a PropertyInfo parameter:
public class CustomNotEmpty<T> : PropertyValidator
{
private PropertyInfo _propertyInfo;
public CustomNotEmpty(PropertyInfo propertyInfo)
: base(string.Format("{0} is required", propertyInfo.Name))
{
_propertyInfo = propertyInfo;
}
protected override bool IsValid(PropertyValidatorContext context)
{
return !IsNullOrEmpty(_propertyInfo, (T)context.Instance);
}
private bool IsNullOrEmpty(PropertyInfo property, T obj)
{
var t = property.PropertyType;
var v = property.GetValue(obj);
// Omitted for clarity...
}
}
And a extension method for IRuleBuilder:
public static class ValidatorExtensions
{
public static IRuleBuilderOptions<T, T> CustomNotEmpty<T>(
this IRuleBuilder<T, T> ruleBuilder, PropertyInfo propertyInfo)
{
return ruleBuilder.SetValidator(new CustomNotEmpty<T>(propertyInfo));
}
}
With this I can change my FooValidator as follows:
public class FooValidator : AbstractValidator<Foo>
{
public FooValidator(Foo obj)
{
// Iterate properties using reflection
var properties = ReflectionHelper.GetShallowPropertiesInfo(obj);
foreach (var prop in properties)
{
// Create rule for each property, based on some data coming from other service...
RuleFor(o => o)
.CustomNotEmpty(obj.GetType().GetProperty(prop.Name))
.When(o =>
{
return true; // do other stuff...
});
}
}
}
And now I'm be able to use Reflection to add rules for specific properties
For reflection i use
RuleFor(x => new obj().GetType().GetProperty(x.Filter.ColumnName)).NotNull();
What I'm trying to do is to create a class with static methods to manage rights of different user types on some types of resources (which are NHibernate entity objects). Specifically I'd like to check the current principal (in an asp.net MVC project) against an object id, to see if he can view or edit an entity. The signature I have in mind is the following:
PermissionManager.CanView<TEntity>(object id);
By now I've done these steps:
1) an interface like this:
public interface ICanAccessQuery<TAccount, TEntity>
where TAccount : IAccountOwner
{
bool CanView(TAccount user, object entityKey);
bool CanEdit(TAccount user, object entityKey);
}
2) some implementations like this one:
public class TeacherCanAccessCourseReportsQuery : ICanAccessQuery<Teacher, CourseReport>
{
public bool CanView(Teacher user, object entityKey)
{
var predicate = PredicateBuilder.Create<CourseReport>(x => x.Id == (long)entityKey);
var conditions = PredicateBuilder.Create<CourseReport>(x => x.Teacher.Id == user.Id);
conditions = conditions.Or(x => x.Teacher.Tutor.Id == user.Id);
conditions = conditions.Or(x => x.CoachingTeachers.Any(t => t.Id == user.Id));
predicate = predicate.And(conditions);
return RepositoryProvider.Get<CourseReport>().Count(predicate) > 0;
}
public bool CanEdit(Teacher user, object entityKey)
{
// similar implementation
}
}
3) a static Configure() method inside my PermissionManager class, to be called in Global.asax:
public static IDictionary<string, object> _permissions = new Dictionary<string, object>();
public static void Configure()
{
_permissions.Add(typeof(Teacher).Name + typeof(CourseReport).Name, new TeacherCanAccessCourseReportsQuery());
}
4) inside the PermissionManager class:
public static bool CanView<TEntity>(object primaryKey, params string[] enabledRoles)
{
var accounts = RepositoryProvider.Get<Account, AccountRepository>();
var principal = Thread.CurrentPrincipal as MyCustomPrincipal;
if (enabledRoles.Any(r => principal.IsInRole(r)))
return true;
IAccountOwner user = accounts.GetUser(principal.AccountId);
var can = false;
var #switch = new Dictionary<Type, Action> {
{ typeof(Teacher), () => can = CanView<Teacher, TEntity>(user as Teacher, primaryKey) },
{ typeof(TrainingCenter), () => can = CanView<TrainingCenter, TEntity>(user as TrainingCenter, primaryKey) }
};
#switch[user.GetType()]();
return can;
}
private static bool CanView<TAccount, TEntity>(TAccount user, object primaryKey)
where TAccount : IAccountOwner
{
var key = typeof(TAccount).Name + typeof(TEntity).Name;
if (_permissions.ContainsKey(key))
{
return (((ICanAccessQuery<TAccount, TEntity>)_permissions[key]).CanView(user, primaryKey);
}
return false;
}
The same methods would be defined for CanEdit... perfectly identical except the method name to be called.
What I'm asking is: is there a better way to define what I have in mind, in a more OOP-way?
I've implemented a better solution that maybe can be interesting for someone.
This is the interface of a "Can I access?" query:
public interface ICanAccessQuery<TAccount, TEntity>
where TAccount : IAccountOwner
where TEntity : IStoredEntity
{
bool CanView(TAccount user, TEntity entity);
bool CanEdit(TAccount user, TEntity entity);
}
My entities now implement an empty interface IStoredEntity to make a constraint.
And this is an example of implementation:
public class TeacherCanAccessOrdersQuery : ICanAccessQuery<Teacher, Order>
{
public bool CanView(Teacher user, Order entity)
{
var predicate = PredicateBuilder.Create<Order>(x => x.Id == entity.Id && x => x.Account.Id == user.Account.Id);
return RepositoryProvider.Get<Order>().Count(predicate) > 0;
}
public bool CanEdit(Teacher user, Order entity)
{
// similar implementation
}
}
Finally, my new AuthorizationProvider class (changed name from PermissionManager, didn't like it):
public class AuthorizationProvider
{
public enum Abilities
{
View,
Edit
};
private static IDictionary<string, object> _authorizations = new Dictionary<string, object>();
// this method should be called at application bootstrap, such as Global.asax in an asp.net app
public static void Configure()
{
_authorizations.Add(typeof(Teacher).Name + typeof(CourseReport).Name, new TeacherCanAccessCourseReportsQuery());
_authorizations.Add(typeof(Teacher).Name + typeof(Order).Name, new TeacherCanAccessOrdersQuery());
// other rules user type-entity type
}
// Can I view entity with primary key X?
public static bool CanI<TEntity>(Abilities ability, object entityKey)
where TEntity : IStoredEntity
{
TEntity entity = RepositoryProvider.Get<TEntity>().Load(entityKey);
return CanI<TEntity>(ability, entity, AccountRoles.Admin);
}
// Can I view entity (and if I have a specific role, I surely can)?
public static bool CanI<TEntity>(Abilities ability, TEntity entity, params string[] authorizedRoles)
where TEntity : IStoredEntity
{
var principal = Thread.CurrentPrincipal as MyCustomPrincipal;
if (authorizedRoles.Any(r => principal.IsInRole(r)))
return true;
var user = RepositoryProvider.Get<Account, AccountRepository>().GetUser(principal.AccountId);
// my system has only two types of users
if (user is Teacher)
{
return Can<Teacher, TEntity>(user as Teacher, ability, entity);
}
else if (user is TrainingCenter)
{
return Can<TrainingCenter, TEntity>(user as TrainingCenter, ability, entity);
}
return false;
}
/// Can user X (view|edit) entity Y?
/// With some reflection I call the needed method. In this way I can add "abilities" to my ICanAccessQuery
/// interface and its implementations without altering this class.
public static bool Can<TAccount, TEntity>(TAccount user, Abilities ability, TEntity entity)
where TAccount : IAccountOwner
where TEntity : IStoredEntity
{
var key = typeof(TAccount).Name + typeof(TEntity).Name;
if (_authorizations.ContainsKey(key))
{
var query = (ICanAccessQuery<TAccount, TEntity>)_authorizations[key];
string methodName = "Can" + ability.ToString();
var method = typeof(ICanAccessQuery<TAccount, TEntity>).GetMethod(methodName);
return (bool)method.Invoke(query, new object[] { user, entity });
}
return false;
}
}
An example of use in an asp.net mvc controller:
public ActionResult Details(long? id)
{
if (!id.HasValue)
return new EmptyResult();
if (!AuthorizationProvider.CanI<CourseReport>(AuthorizationProvider.Abilities.View, id.Value))
return RedirectToAccessDenied();
// etc.
}
I am trying to apply the new mocking of EF6 to my existing code.
I have a class that Extends DbSet. One of the methods call the base class (BdSet) Create method. Here is the a sample code (not the complete solution or real names):
public class DerivedDbSet<TEntity> : DbSet<TEntity>, IKeyValueDbSet<TEntity>, IOrderedQueryable<TEntity> where TEntity : class
{
public virtual bool Add(string value1, string value2) {
var entity = Create(); // There is no direct implementation of the Create method it is calling the base method
// Do something with the values
this.Add(entity);
return true;
}
}
I am mocking using the Test Doubles sample (here is the peace of code):
var data = new List<DummyEntity> {
new DummyEntity { Value1 = "First", Value2 = "001" },
new DummyEntity { Value1 = "Second", Value2 = "002" }
}.AsQueryable();
var mock = new Mock<DerivedDbSet<DummyEntity>>();
mock.CallBase = true;
mock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(source.Provider);
mock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(source.Expression);
mock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(source.ElementType);
mock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(source.GetEnumerator());
I've set the CallBase property to true to try to force the call to the base class...
But I keep receiving the following error:
System.NotImplementedException: The member 'Create' has not been implemented on type 'DerivedDbSet1Proxy' which inherits from 'DbSet1'. Test doubles for 'DbSet`1' must provide implementations of methods and properties that are used.
I want the call of create to fallback to the default implementation in DbSet.
Can someone help me with that?
After some struggle with the internal functions and async references of mocking a DbSet I came out with a helper class that solved most of my problems and might serve as base to someone implementation.
Here is the code:
public static class MockHelper
{
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider {
private readonly IQueryProvider _inner;
internal TestDbAsyncQueryProvider(IQueryProvider inner) { _inner = inner; }
public IQueryable CreateQuery(Expression expression) { return new TestDbAsyncEnumerable<TEntity>(expression); }
public IQueryable<TElement> CreateQuery<TElement>(Expression expression) { return new TestDbAsyncEnumerable<TElement>(expression); }
public object Execute(Expression expression) { return _inner.Execute(expression); }
public TResult Execute<TResult>(Expression expression) { return _inner.Execute<TResult>(expression); }
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute(expression)); }
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute<TResult>(expression)); }
}
internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T> {
public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { }
public TestDbAsyncEnumerable(Expression expression) : base(expression) { }
public IDbAsyncEnumerator<T> GetAsyncEnumerator() { return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); }
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() { return GetAsyncEnumerator(); }
public IQueryProvider Provider { get { return new TestDbAsyncQueryProvider<T>(this); } }
}
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> {
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner) { _inner = inner; }
public void Dispose() { _inner.Dispose(); }
public Task<bool> MoveNextAsync(CancellationToken cancellationToken) { return Task.FromResult(_inner.MoveNext()); }
public T Current { get { return _inner.Current; } }
object IDbAsyncEnumerator.Current { get { return Current; } }
}
public static Mock<TDbSet> CreateDbSet<TDbSet, TEntity>(IList<TEntity> data, Func<object[], TEntity> find = null)
where TDbSet : class, IDbSet<TEntity>
where TEntity : class, new() {
var source = data.AsQueryable();
var mock = new Mock<TDbSet> { CallBase = true };
mock.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(source.Expression);
mock.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(source.ElementType);
mock.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(source.GetEnumerator());
mock.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<TEntity>(source.Provider));
mock.As<IDbAsyncEnumerable<TEntity>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<TEntity>(data.GetEnumerator()));
mock.As<IDbSet<TEntity>>().Setup(m => m.Create()).Returns(new TEntity());
mock.As<IDbSet<TEntity>>().Setup(m => m.Add(It.IsAny<TEntity>())).Returns<TEntity>(i => { data.Add(i); return i; });
mock.As<IDbSet<TEntity>>().Setup(m => m.Remove(It.IsAny<TEntity>())).Returns<TEntity>(i => { data.Remove(i); return i; });
if (find != null) mock.As<IDbSet<TEntity>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns(find);
return mock;
}
public static Mock<DbSet<TEntity>> CreateDbSet<TEntity>(IList<TEntity> data, Func<object[], TEntity> find = null)
where TEntity : class, new() {
return CreateDbSet<DbSet<TEntity>, TEntity>(data, find);
}
}
And here is a use sample (based on the names I've given before):
var data = new List<DummyEntity> {
new DummyEntity { Value1 = "First", Value2 = "001" } },
new DummyEntity { Value1 = "Second", Value2 = "002" } }
};
var mockDummyEntities = MockHelper.CreateDbSet<DerivedDbSet<DummyEntities>, DummyEntities>(data, i => data.FirstOrDefault(k => k.Value2 == (string)i[0]));
var mockContext = new Mock<DummyDbContext>();
mockContext.Setup(c => c.DummyEntities).Returns(mockDummyEntities.Object);
Any suggestions on how to improve this solution is very welcome.
Regards
This is a modified version based on Andre that worked for me. Note, that I did not need the async references. Code will add all derived classes (if any)
Usage:
/// <summary>
///
/// </summary>
[TestMethod]
public void SomeTest()
{
//Setup
var mockContext = new Mock<FakeDbContext>();
//SomeClass can be abstract or concrete
mockContext.createFakeDBSet<SomeClass>();
var db = mockContext.Object;
//Setup create(s) if needed on concrete classes
//Mock.Get(db.Set<SomeOtherClass>()).Setup(x => x.Create()).Returns(new SomeOtherClass());
//DO Stuff
var list1 = db.Set<SomeClass>().ToList();
//SomeOtherClass derived from SomeClass
var subList1 = db.Set<SomeOtherClass>().ToList();
CollectionAssert.AreEquivalent(list1.OfType<SomeOtherClass>.ToList(), subList1);
}
Code:
/// <summary>
/// http://stackoverflow.com/questions/21943328/ef6-mocking-derived-dbsets
/// </summary>
public static class MoqSetupExtensions
{
static IEnumerable<Type> domainTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes());
public static Mock<DbSet<T>> createFakeDBSet<T>(this Mock<FakeDbContext> db, List<T> list = null, Func<List<T>, object[], T> find = null, bool createDerivedSets = true) where T : class
{
list = list ?? new List<T>();
var data = list.AsQueryable();
//var mockSet = MockHelper.CreateDbSet(list, find);
var mockSet = new Mock<DbSet<T>>() { CallBase = true };
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(() => { return data.Provider; });
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(() => { return data.Expression; });
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(() => { return data.ElementType; });
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => { return list.GetEnumerator(); });
mockSet.Setup(m => m.Add(It.IsAny<T>())).Returns<T>(i => { list.Add(i); return i; });
mockSet.Setup(m => m.AddRange(It.IsAny<IEnumerable<T>>())).Returns<IEnumerable<T>>((i) => { list.AddRange(i); return i; });
mockSet.Setup(m => m.Remove(It.IsAny<T>())).Returns<T>(i => { list.Remove(i); return i; });
if (find != null) mockSet.As<IDbSet<T>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns<object[]>((i) => { return find(list, i); });
//mockSet.Setup(m => m.Create()).Returns(new T());
db.Setup(x => x.Set<T>()).Returns(mockSet.Object);
//Setup all derived classes
if (createDerivedSets)
{
var type = typeof(T);
var concreteTypes = domainTypes.Where(x => type.IsAssignableFrom(x) && type != x).ToList();
var method = typeof(MoqSetupExtensions).GetMethod("createFakeDBSetSubType");
foreach (var item in concreteTypes)
{
var invokeResult = method.MakeGenericMethod(type, item)
.Invoke(null, new object[] { db, mockSet });
}
}
return mockSet;
}
public static Mock<DbSet<SubType>> createFakeDBSetSubType<BaseType, SubType>(this Mock<FakeDbContext> db, Mock<DbSet<BaseType>> baseSet)
where BaseType : class
where SubType : class, BaseType
{
var dbSet = db.Object.Set<BaseType>();
var mockSet = new Mock<DbSet<SubType>>() { CallBase = true };
mockSet.As<IQueryable<SubType>>().Setup(m => m.Provider).Returns(() => { return dbSet.OfType<SubType>().Provider; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.Expression).Returns(() => { return dbSet.OfType<SubType>().Expression; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.ElementType).Returns(() => { return dbSet.OfType<SubType>().ElementType; });
mockSet.As<IQueryable<SubType>>().Setup(m => m.GetEnumerator()).Returns(() => { return dbSet.OfType<SubType>().GetEnumerator(); });
mockSet.Setup(m => m.Add(It.IsAny<SubType>())).Returns<SubType>(i => { dbSet.Add(i); return i; });
mockSet.Setup(m => m.AddRange(It.IsAny<IEnumerable<SubType>>())).Returns<IEnumerable<SubType>>((i) => { dbSet.AddRange(i); return i; });
mockSet.Setup(m => m.Remove(It.IsAny<SubType>())).Returns<SubType>(i => { dbSet.Remove(i); return i; });
mockSet.As<IDbSet<SubType>>().Setup(m => m.Find(It.IsAny<object[]>())).Returns<object[]>((i) => { return dbSet.Find(i) as SubType; });
baseSet.Setup(m => m.Create<SubType>()).Returns(() => { return mockSet.Object.Create(); });
db.Setup(x => x.Set<SubType>()).Returns(mockSet.Object);
return mockSet;
}
}
Microsoft published a very well explained guide providing an in-memory implementation of DbSet which has a complete implemention for all the methods on DbSet.
Check the article at http://msdn.microsoft.com/en-us/data/dn314431.aspx#doubles
I have inherited a codebase which contains a lot of upcasting.
I've got tired of all of the switch statements on types with ad-hoc casts inside the code.
I wrote a couple of functions for switching on the type of a variable and getting access to to that variable appropriately cast in the corresponding "case" statement.
As I am relatively new to dot net I thought that perhaps I was coming at it from completely the wrong angle.
If I'm not perhaps this will be useful to someone else.
NB c# specific answers are less useful as the code-base is mostly Visual Basic. I have posted c# code because the c# community is much larger here on stackexchange.
This is an example of the usage:
class Program
{
static void Main(string[] args)
{
List<object> bobbies = new List<object>();
bobbies.Add(new Hashtable());
bobbies.Add(string.Empty);
bobbies.Add(new List<string>());
bobbies.Add(108);
bobbies.Add(10);
bobbies.Add(typeof(string));
bobbies.Add(typeof(string));
bool b = true;
// as an expression
foreach (var bob in bobbies)
Console.WriteLine(
TypeSwitch.on<String>(bob)
.inCase<Hashtable>(x =>
"gotta HASHTABLE")
.inCase<string>(x =>
"its a string " + x)
.inCase<IEnumerable<Object>>(x =>
"I got " + x.Count<Object>().ToString() + " elements")
.inCase<int>(x => (x > 10), x =>
"additional conditions")
.inCase(b, x => {
b = false;
return "non lazy conditions"; })
.otherwise(p =>
"default case"));
// as a statement
foreach (var bob in bobbies)
TypeSwitch.on(bob)
.inCase<Hashtable>(x => Console.WriteLine("one"))
.inCase<String>(x => Console.WriteLine("two"))
.inCase<int>(x => Console.WriteLine("three"))
.otherwise(x => Console.WriteLine("I give up"));
Console.ReadLine();
}
}
and here is the implementation
public static class TypeSwitch
{
public class TypeSwitcher
{
private object _thing;
public TypeSwitcher(object thang) { _thing = thang; }
public TypeSwitcher inCase<TryType>(Func<TryType, bool> guard, Action<TryType> action) {
if (_thing is TryType) {
var t = (TryType)_thing;
if (guard(t)) {
_thing = null;
action(t); } }
return this; }
public TypeSwitcher inCase<TryType>(bool condition, Action<TryType> action) { return inCase<TryType>(p => condition, action); }
public TypeSwitcher inCase<TryType>(Action<TryType> action) { return inCase<TryType>(true, action); }
public TypeSwitcher inCase(bool cond, Action<object> action) { return inCase<object>(cond, action); }
public void otherwise(Action<object> action) { this.inCase<object>(action); }
}
// for case statements with a return value:
public class TypeSwitcherExpression<ResultType>
{
private object _thing;
private ResultType _result;
public ResultType Result { get { return _result; } }
public TypeSwitcherExpression(object thang) { _thing = thang; }
public TypeSwitcherExpression<ResultType> inCase<TryType>(Func<TryType, bool> guard, Func<TryType, ResultType> action) {
if (_thing is TryType) {
var t = (TryType)_thing;
if (guard(t)) {
_thing = null;
_result = action(t); } }
return this; }
public TypeSwitcherExpression<ResultType> inCase<TryType>(bool condition, Func<TryType, ResultType> action) { return inCase<TryType>(p => condition, action); }
public TypeSwitcherExpression<ResultType> inCase<TryType>(Func<TryType, ResultType> action) { return inCase<TryType>(true, action); }
public TypeSwitcherExpression<ResultType> inCase(bool cond, Func<object, ResultType> action) { return inCase<object>(cond, action); }
public ResultType otherwise(Func<object, ResultType> action) { this.inCase<object>(action); return Result; }
}
static public TypeSwitcher on(object thing)
{ return new TypeSwitcher(thing); }
static public TypeSwitcherExpression<ResultType> on<ResultType>(object thing)
{ return new TypeSwitcherExpression<ResultType>(thing); }
public static TypeSwitcher switchOnType(this Object thing)
{ return new TypeSwitcher(thing); }
public static TypeSwitcherExpression<ResultType> switchOnType<ResultType>(this Object thing)
{ return new TypeSwitcherExpression<ResultType>(thing); }
}
Edit 1:
Replaced delegates with Action and Func. Added extension method in case you like that sort of thing.
Edit 2:
Use Is to check type of object
Here is my suggestion
namespace xx{
public static class TypeSwitcher
{
public static dynamic inCase<T>(this object item,Func<dynamic> function)
{
if (item.GetType() == typeof(T))
return function();
else
return "";
}
}
}
using xx;
static void Main(string[] args)
{
List<object> bobbies = new List<object>();
bobbies.Add(new Hashtable());
bobbies.Add(string.Empty);
bobbies.Add(new List<string>());
bobbies.Add(108);
bobbies.Add(10);
bobbies.Add(typeof(string));
bobbies.Add(typeof(string));
foreach (var item in bobbies)
{
Console.WriteLine(item.inCase<Hashtable>(() => "one"));
Console.WriteLine(item.inCase<String>(() => "two"));
Console.WriteLine(item.inCase<int>(() => "three"));
}
Console.ReadLine();
}