public TestDbContext(string nameOrConnectionString, object stringParameter, object objectParameter, InjectionSet classParameter, IEnumerable<int> interfaceParameter) : base(nameOrConnectionString)
	    {
	        StringParameter = stringParameter;
	        ObjectParameter = objectParameter;
	        ClassParameter = classParameter;
	        InterfaceParameter = interfaceParameter;
	    }
		public void Non_virtual_method_should_be_rejected()
		{
			// arrange
			var injections = new InjectionSet(new NonVirtualWorkInjection());
			var assemblyBuilder = new InjectedAssemblyBuilder(injections, tb => new InjectedTypeBuilder(tb));
			
			// act + assert
			Assert.That(() => assemblyBuilder.Append(typeof(BaseType)), Throws.ArgumentException);
		}
		public void GetInjectionTypes_should_return_interfaces_instead_of_indirect_types()
		{
			// arrange
			var set = new InjectionSet(new DoWorkInjection(), new DoWorkInjection2());
			
			// act
			var injectionTypes = set.GetInjectionTypes();

			// assert
			Assert.That(injectionTypes, Is.EquivalentTo(new[] { typeof(IDoWorkInjection) }));
		}
		public static BaseType Create(Type targetType, InjectionSet injectionSet)
		{
			if (!typeof(BaseType).IsAssignableFrom(targetType))
				throw new ArgumentException(string.Format("Target type {0} should be inherited from {1}.", targetType, typeof(BaseType)));

			var constructor = targetType.GetConstructor(new[] { typeof(InjectionSet) });
			if (constructor == null)
				throw new InvalidOperationException(
					string.Format("Constructor with injection set does not supported by {0}.", targetType));
			return (BaseType)constructor.Invoke(new object[] { injectionSet });
		}
		public void GetInjections_should_return_direct_types_or_interfaces()
		{
			// arrange
			var set = new InjectionSet(new DoWorkInjection(), new DoWorkInjectionDirect());

			// act
			var injection1 = set.GetInjections<IDoWorkInjection>();
			var injection2 = set.GetInjections<DoWorkInjection>();
			var injection3 = set.GetInjections<DoWorkInjectionDirect>();

			// assert
			Assert.That(injection1, Is.Not.Empty);
			Assert.That(injection2, Is.Empty);
			Assert.That(injection3, Is.Not.Empty);
		}
		public InjectedAssemblyBuilder(InjectionSet injectionSet, Func<TypeBuilder, InjectedTypeBuilder> injectedTypeBuilderFactory,
			bool saveAssemblyToDisk = false)
		{
			if (injectionSet == null) throw new ArgumentNullException("injectionSet");
			if (injectedTypeBuilderFactory == null) throw new ArgumentNullException("injectedTypeBuilderFactory");

			_injectionSet = injectionSet;
			_injectedTypeBuilderFactory = injectedTypeBuilderFactory;

			var assemblyName = new AssemblyName { Name = injectionSet.UniqueKey + Guid.NewGuid() };

			_assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
				saveAssemblyToDisk ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run);

			_moduleBuilder = saveAssemblyToDisk ? _assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".mod")
				: _assemblyBuilder.DefineDynamicModule(assemblyName.Name, false);
		}
		public void EntityValidation_should_be_injectable()
		{
			// arrange
			var injection = new TestEntityValidationInjection();
			var injectionSet = new InjectionSet(injection, new TestModelCreationInjection());
			var factory = new DbContextFactory();

			// act
			using (var context = Create(factory, injectionSet))
			{
				context.ActionTypes.Add(new ActionType());
				
				context.GetValidationErrors();
			}

			// assert
			Assert.That(injection.Entries.Count, Is.EqualTo(1));
		}
		public void Base_methods_and_generic_injection_should_be_called()
		{
			// arrange
			var injections = new InjectionSet(new DoWorkInjection(), new ProtectedWorkInjection());
			var assemblyBuilder = new InjectedAssemblyBuilder(injections, tb => new InjectedTypeBuilder(tb));
			var type = assemblyBuilder.Append(typeof(GenericBaseType<int, string>));
			var newType = BaseTypeHelper.Create(type, injections);

			// act
			newType.DoWork("1");

			// assert
			Assert.That(string.Join(",", newType.CallsLog), Is.EqualTo("BaseType(),BaseType.DoWork(1),DoWorkInjection.DoWork(1)"));

			// act
			newType.CallsLog.Clear();
			newType.CallProtectedWork("2");

			// assert
			Assert.That(string.Join(",", newType.CallsLog), Is.EqualTo("BaseType.ProtectedWork(2),ProtectedWorkInjection.ProtectedWork(2)"));
		}
		public void SaveChanges_should_be_injectable()
		{
			// arrange
			var injection = new TestSaveChangesInjection();
			var injectionSet = new InjectionSet(injection);
			var factory = new DbContextFactory();
			int count;

			// act
			using (var context = Create(factory, injectionSet))
			{
				count = context.SaveChanges();
			}

			// assert
			Assert.That(injection.BeforeList.Count, Is.EqualTo(1));
			Assert.That(injection.AfterList.Count, Is.EqualTo(1));
			Assert.That(injection.AfterList[0], Is.EqualTo(injection.BeforeList[0]));
			
			Assert.That(count, Is.EqualTo(0));
		}
		public void ModelCreation_should_be_injectable_and_called_once()
		{
			// ReSharper disable ReturnValueOfPureMethodIsNotUsed
			
			// arrange
			var injection = new TestModelCreationInjection();
			var injectionSet = new InjectionSet(injection);
			var factory = new DbContextFactory();

			// act
			using (var context1 = Create(factory, injectionSet))
			{
				context1.ActionTypes.Count();
			}

			using (var context2 = Create(factory, injectionSet))
			{
				context2.ActionTypes.Count();
			}

			// assert
			Assert.That(injection.ModelBuilders.Count, Is.EqualTo(1));
			// ReSharper restore ReturnValueOfPureMethodIsNotUsed
		}
		public BasicDbContext_generated(InjectionSet ps, string name) : base(name)
		{
			_injectionSet = ps;
		}
		public void Should_be_only_one_type_for_one_injection_set()
		{
			// arrange
			var injectionSet = new InjectionSet(new TestModelCreationInjection());
			var factory = new DbContextFactory();
			Type type1;
			Type type2;

			// act
			using (var context1 = Create(factory, injectionSet))
			{
				type1 = context1.GetType();
			}

			using (var context2 = Create(factory, injectionSet))
			{
				type2 = context2.GetType();
			}

			// assert
			Assert.That(type1, Is.EqualTo(type2));
		}
		private static BasicDbContext Create(DbContextFactory factory, InjectionSet injectionSet)
		{
			return factory.Create<BasicDbContext>(injectionSet, "EntityFrameworkInject");
		}