├── src
├── ScaffoldR.EntityFramework
│ ├── packages.config
│ ├── Entities
│ │ ├── EntityFrameworkUnitOfWork.cs
│ │ ├── EntityReaderAdapter.cs
│ │ ├── EntityWriterAdapter.cs
│ │ └── EntityFrameworkRepository.cs
│ ├── ScaffoldR.EntityFramework.nuspec
│ ├── App.config
│ ├── Extensions
│ │ └── ContainerExtensions.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── ScaffoldR.EntityFramework.csproj
├── ScaffoldR
│ ├── Core
│ │ ├── Entities
│ │ │ ├── Entity.cs
│ │ │ ├── IEntityReader.cs
│ │ │ ├── IEntityWriter.cs
│ │ │ └── EntityWithId.cs
│ │ ├── Views
│ │ │ ├── IViewModel.cs
│ │ │ ├── IProcessViewModels.cs
│ │ │ └── IHandleViewModel.cs
│ │ ├── Transactions
│ │ │ ├── TransactionalAttribute.cs
│ │ │ └── IProcessTransactions.cs
│ │ ├── Commands
│ │ │ ├── ICommand.cs
│ │ │ ├── IProcessCommands.cs
│ │ │ ├── ICreateEntityCommand.cs
│ │ │ └── IHandleCommand.cs
│ │ ├── Events
│ │ │ ├── IEvent.cs
│ │ │ ├── IProcessEvents.cs
│ │ │ ├── RaiseEventAttribute.cs
│ │ │ ├── ITriggerEvent.cs
│ │ │ └── IHandleEvent.cs
│ │ ├── Tasks
│ │ │ └── ITaskFactory.cs
│ │ ├── Queries
│ │ │ ├── IQuery.cs
│ │ │ ├── IProcessQueries.cs
│ │ │ └── IHandleQuery.cs
│ │ ├── Validation
│ │ │ └── IProcessValidation.cs
│ │ └── Extensions
│ │ │ └── ReflectionExtensions.cs
│ ├── packages.config
│ ├── Infrastructure
│ │ ├── Tasks
│ │ │ └── TaskFactory.cs
│ │ ├── Transactions
│ │ │ └── EmptyTransactionProcessor.cs
│ │ ├── FluentValidation
│ │ │ ├── ValidateNothingDecorator.cs
│ │ │ ├── ValidateCommandDecorator.cs
│ │ │ ├── ValidateQueryDecorator.cs
│ │ │ ├── ValidationProcessor.cs
│ │ │ └── SimpleInjectorValidatorFactory.cs
│ │ ├── CompositionRoot
│ │ │ ├── Packages
│ │ │ │ ├── TaskPackage.cs
│ │ │ │ ├── EventPackage.cs
│ │ │ │ ├── TransactionPackage.cs
│ │ │ │ ├── ValidationPackage.cs
│ │ │ │ ├── ViewModelPackage.cs
│ │ │ │ ├── QueryPackage.cs
│ │ │ │ └── CommandPackage.cs
│ │ │ ├── IPackageScaffoldR.cs
│ │ │ ├── CompositionRootSettings.cs
│ │ │ └── ContainerExtensions.cs
│ │ ├── Events
│ │ │ ├── EventProcessor.cs
│ │ │ ├── MultipleDispatchEventTrigger.cs
│ │ │ └── TriggerEventWhenHandlersExistDecorator.cs
│ │ ├── Commands
│ │ │ ├── CommandProcessor.cs
│ │ │ ├── CommandNotNullDecorator.cs
│ │ │ ├── CommandTransactionDecorator.cs
│ │ │ ├── CommandEventProcessingDecorator.cs
│ │ │ └── CommandLifetimeScopeDecorator.cs
│ │ ├── Queries
│ │ │ ├── QueryProcessor.cs
│ │ │ ├── QueryNotNullDecorator.cs
│ │ │ ├── QueryLifetimeScopeDecorator.cs
│ │ │ └── QueryEventProcessingDecorator.cs
│ │ └── Views
│ │ │ ├── ViewModelWithArgumentNotNullDecorator.cs
│ │ │ ├── ViewModelProcessor.cs
│ │ │ ├── ViewModelLifetimeScopeDecorator.cs
│ │ │ └── ViewModelWithArgumentLifetimeScopeDecorator.cs
│ ├── ScaffoldR.nuspec
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── ScaffoldR.csproj
├── ScaffoldR.EntityFramework.Tests
│ ├── Fakes
│ │ ├── FakeCustomer.cs
│ │ ├── FakeDbContext.cs
│ │ └── FakeDbContextInitializer.cs
│ ├── Helpers
│ │ ├── MockedDbContext.cs
│ │ └── EntityFrameworkMockHelper.cs
│ ├── Entities
│ │ ├── EntityFrameworkUnitOfWorkTests.cs
│ │ └── EntityFrameworkRepositoryTests.cs
│ ├── App.config
│ ├── CompositionRoot
│ │ ├── CompositionRootTests.cs
│ │ └── CompositionRootFixture.cs
│ ├── packages.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── ScaffoldR.EntityFramework.Tests.csproj
├── ScaffoldR.Tests
│ ├── Infrastructure
│ │ ├── Events
│ │ │ ├── Fakes
│ │ │ │ └── FakeEventWithoutValidation.cs
│ │ │ ├── EventProcessorTests.cs
│ │ │ ├── MultipleDispatchEventTriggerTests.cs
│ │ │ └── TriggerEventWhenHandlersExistDecoratorTests.cs
│ │ ├── Queries
│ │ │ ├── Fakes
│ │ │ │ ├── FakeQueryWithoutValidator.cs
│ │ │ │ └── FakeQueryWithValidator.cs
│ │ │ ├── QueryProcessorTests.cs
│ │ │ ├── CompositionRootTests.cs
│ │ │ ├── QueryLifetimeScopeDecoratorTests.cs
│ │ │ └── QueryEventProcessingDecoratorTests.cs
│ │ ├── Commands
│ │ │ ├── Fakes
│ │ │ │ ├── FakeCommandWithoutValidator.cs
│ │ │ │ └── FakeCommandWithValidator.cs
│ │ │ ├── CommandProcessorTests.cs
│ │ │ ├── CompositionRootTests.cs
│ │ │ ├── CommandLifetimeScopeDecoratorTests.cs
│ │ │ ├── CommandTransactionDecoratorTests.cs
│ │ │ └── CommandEventProcessingDecoratorTests.cs
│ │ ├── Views
│ │ │ ├── Fakes
│ │ │ │ └── FakeViewModel.cs
│ │ │ └── ViewModelProcessorTests.cs
│ │ ├── FluentValidation
│ │ │ ├── NerveFrameworkValidatorFactoryTests.cs
│ │ │ ├── ValidationProcessorTests.cs
│ │ │ ├── CompositionRootTests.cs
│ │ │ ├── ValidateQueryDecoratorTests.cs
│ │ │ └── ValidateCommandDecoratorTests.cs
│ │ ├── CompositionRoot
│ │ │ ├── CompositionRootTests.cs
│ │ │ └── CompositionRootFixture.cs
│ │ └── Entities
│ │ │ └── CompositionRootTests.cs
│ ├── packages.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── ScaffoldR.Tests.csproj
└── ScaffoldR.sln
├── .gitattributes
├── tools
├── Build.ps1
└── BuildFunctions.ps1
├── .gitignore
├── README.md
└── LICENSE
/src/ScaffoldR.EntityFramework/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Entities/Entity.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Entities
2 | {
3 | ///
4 | /// A single unit of relational data that can be identified by a primary key.
5 | ///
6 | public abstract class Entity
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Views/IViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Views
2 | {
3 | ///
4 | /// Specifices that the target class is a view model. This is a marker interface and has no methods.
5 | ///
6 | public interface IViewModel
7 | {
8 | // Marker interface
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/ScaffoldR/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Transactions/TransactionalAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ScaffoldR.Core.Transactions
4 | {
5 | ///
6 | /// Marks the class as being a transactional call.
7 | ///
8 | [AttributeUsage(AttributeTargets.Class)]
9 | public class TransactionalAttribute : Attribute
10 | {
11 |
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Commands/ICommand.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Events;
2 |
3 | namespace ScaffoldR.Core.Commands
4 | {
5 | ///
6 | /// Specifices that the target class is a command. This is a marker interface and has no methods.
7 | ///
8 | public interface ICommand : IEvent
9 | {
10 | // Marker interface
11 | }
12 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Events/IEvent.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Events
2 | {
3 | ///
4 | /// Specifices that the target class can be notified by implemented . This is a marker interface and has no methods.
5 | ///
6 | public interface IEvent
7 | {
8 | // Marker interface
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Fakes/FakeCustomer.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using ScaffoldR.Core.Entities;
3 |
4 | namespace ScaffoldR.EntityFramework.Tests.Fakes
5 | {
6 | public class FakeCustomer : EntityWithId
7 | {
8 |
9 | public string FirstName { get; set; }
10 |
11 | public string LastName { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Tasks/TaskFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using ScaffoldR.Core.Tasks;
4 |
5 | namespace ScaffoldR.Infrastructure.Tasks
6 | {
7 | internal sealed class TaskFactory : ITaskFactory
8 | {
9 | public void StartTask(Action action)
10 | {
11 | Task.Factory.StartNew(action);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Transactions/EmptyTransactionProcessor.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Transactions;
2 |
3 | namespace ScaffoldR.Infrastructure.Transactions
4 | {
5 | internal sealed class EmptyTransactionProcessor : IProcessTransactions
6 | {
7 | public void Execute()
8 | {
9 | // I do nothing, this interface is implemented in sub packages.
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Commands/IProcessCommands.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Commands
2 | {
3 | ///
4 | /// Processes commands.
5 | ///
6 | public interface IProcessCommands
7 | {
8 | ///
9 | /// Executes the command.
10 | ///
11 | /// The command to be executed.
12 | void Execute(ICommand command);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Transactions/IProcessTransactions.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Transactions
2 | {
3 | ///
4 | /// Executes the transaction, e.g. synchronizes data state changes with an underlying data store.
5 | ///
6 | public interface IProcessTransactions
7 | {
8 | ///
9 | /// Executes the transaction
10 | ///
11 | void Execute();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Events/IProcessEvents.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Events
2 | {
3 | ///
4 | /// Processes events.
5 | ///
6 | public interface IProcessEvents
7 | {
8 | ///
9 | /// Triggers the event.
10 | ///
11 | /// The event to be raised.
12 | /// An async Task
13 | void Raise(IEvent evt);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Tasks/ITaskFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ScaffoldR.Core.Tasks
4 | {
5 | ///
6 | /// Starts a task.
7 | ///
8 | public interface ITaskFactory
9 | {
10 | ///
11 | /// Starts a task with the specified action.
12 | ///
13 | /// The action to start in the task.
14 | void StartTask(Action action);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/FluentValidation/ValidateNothingDecorator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 |
3 | namespace ScaffoldR.Infrastructure.FluentValidation
4 | {
5 | ///
6 | /// Adds an unregistered type resolution for objects missing an IValidator.
7 | ///
8 | /// The type.
9 | internal sealed class ValidateNothingDecorator : AbstractValidator
10 | {
11 |
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Helpers/MockedDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using Moq;
5 |
6 | namespace ScaffoldR.EntityFramework.Tests.Helpers
7 | {
8 | public class MockedDbContext : Mock where TContext : DbContext
9 | {
10 | private Dictionary _tables;
11 |
12 | public Dictionary Tables => _tables ?? (_tables = new Dictionary());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Events/RaiseEventAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ScaffoldR.Core.Events
4 | {
5 | ///
6 | /// Marks the class that it able to raise events after execution.
7 | ///
8 | [AttributeUsage(AttributeTargets.Class)]
9 | public class RaiseEventAttribute : Attribute
10 | {
11 | ///
12 | /// Whether the events should be raised or not
13 | ///
14 | public bool Enabled { get; set; } = true;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/TaskPackage.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Tasks;
2 | using ScaffoldR.Infrastructure.Tasks;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
6 | {
7 | internal sealed class TaskPackage : IPackageScaffoldR
8 | {
9 | public void RegisterServices(Container container, CompositionRootSettings settings)
10 | {
11 | container.Register(Lifestyle.Singleton);
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Events/ITriggerEvent.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Events
2 | {
3 | ///
4 | /// Triggers events
5 | ///
6 | ///
7 | public interface ITriggerEvent where TEvent : IEvent
8 | {
9 | ///
10 | /// Triggers the event handler of .
11 | ///
12 | /// The event which should be triggered.
13 | void Trigger(TEvent evt);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Events/Fakes/FakeEventWithoutValidation.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Events;
2 |
3 | namespace ScaffoldR.Tests.Infrastructure.Events.Fakes
4 | {
5 | public class FakeEventWithoutValidation : IEvent
6 | {
7 | public string ReturnValue { get; internal set; }
8 | }
9 |
10 | public class HandleFakeEventWithoutValidation : IHandleEvent
11 | {
12 | public void Handle(FakeEventWithoutValidation @event)
13 | {
14 | @event.ReturnValue = "faked";
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Queries/Fakes/FakeQueryWithoutValidator.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Queries;
2 |
3 | namespace ScaffoldR.Tests.Infrastructure.Queries.Fakes
4 | {
5 | public class FakeQueryWithoutValidator : IQuery
6 | {
7 | public string ReturnValue { get; internal set; }
8 | }
9 |
10 | public class HandleFakeQueryWithoutValidator : IHandleQuery
11 | {
12 | public string Handle(FakeQueryWithoutValidator query)
13 | {
14 | return "faked";
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Commands/ICreateEntityCommand.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Entities;
2 |
3 | namespace ScaffoldR.Core.Commands
4 | {
5 | ///
6 | /// Defines the command as an entity creation command.
7 | ///
8 | /// The entity type which should be created.
9 | public interface ICreateEntityCommand : ICommand where TEntity : Entity
10 | {
11 | ///
12 | /// The created entity instance.
13 | ///
14 | TEntity CreatedEntity { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Queries/IQuery.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Events;
2 |
3 | namespace ScaffoldR.Core.Queries
4 | {
5 | // ReSharper disable UnusedTypeParameter
6 | ///
7 | /// Specifices that the target class is a query with the return type of . This is a marker interface and has no methods.
8 | ///
9 | /// The return type of the query.
10 | public interface IQuery : IEvent
11 | {
12 | // Marker interface
13 | }
14 | // ReSharper restore UnusedTypeParameter
15 | }
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/Fakes/FakeCommandWithoutValidator.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Commands;
2 |
3 | namespace ScaffoldR.Tests.Infrastructure.Commands.Fakes
4 | {
5 | public class FakeCommandWithoutValidator : ICommand
6 | {
7 | public string ReturnValue { get; internal set; }
8 | }
9 |
10 | public class HandleFakeCommandWithoutValidator : IHandleCommand
11 | {
12 | public void Handle(FakeCommandWithoutValidator command)
13 | {
14 | command.ReturnValue = "faked";
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Commands/IHandleCommand.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Commands
2 | {
3 | ///
4 | /// Handles the .
5 | ///
6 | /// The command which should be handled.
7 | public interface IHandleCommand where TCommand : ICommand
8 | {
9 | ///
10 | /// Handles the .
11 | ///
12 | /// The command.
13 | /// An awaitable task.
14 | void Handle(TCommand command);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Events/IHandleEvent.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Events
2 | {
3 | ///
4 | /// Handles the .
5 | ///
6 | /// The event which should be handled.
7 | public interface IHandleEvent where TEvent : IEvent
8 | {
9 | ///
10 | /// Handles the .
11 | ///
12 | /// The which should be handled.
13 | ///
14 | void Handle(TEvent evt);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Entities/EntityFrameworkUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Entity;
3 | using ScaffoldR.Core.Transactions;
4 |
5 | namespace ScaffoldR.EntityFramework.Entities
6 | {
7 | internal sealed class EntityFrameworkUnitOfWork : IProcessTransactions
8 | {
9 | private readonly Func _contextProvider;
10 |
11 | public EntityFrameworkUnitOfWork(Func contextProvider)
12 | {
13 | _contextProvider = contextProvider;
14 | }
15 |
16 | public void Execute()
17 | {
18 | _contextProvider().SaveChanges();
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Entities/EntityReaderAdapter.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using ScaffoldR.Core.Entities;
3 |
4 | namespace ScaffoldR.EntityFramework.Entities
5 | {
6 | internal sealed class EntityReaderAdapter : IEntityReader where TEntity : Entity
7 | {
8 | private readonly EntityFrameworkRepository _repository;
9 |
10 | public EntityReaderAdapter(EntityFrameworkRepository repository)
11 | {
12 | _repository = repository;
13 | }
14 |
15 | public IQueryable Query()
16 | {
17 | return _repository.Query();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Queries/IProcessQueries.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ScaffoldR.Core.Queries
4 | {
5 | ///
6 | /// Processes queries.
7 | ///
8 | public interface IProcessQueries
9 | {
10 | ///
11 | /// Executes the query.
12 | ///
13 | /// The result of the query.
14 | /// The query.
15 | /// The query result object.
16 | /// If the query is null.
17 | TResult Execute(IQuery query);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Events/EventProcessor.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Events;
2 | using SimpleInjector;
3 |
4 | namespace ScaffoldR.Infrastructure.Events
5 | {
6 | internal sealed class EventProcessor : IProcessEvents
7 | {
8 | private readonly Container _container;
9 |
10 | public EventProcessor(Container container)
11 | {
12 | _container = container;
13 | }
14 |
15 | public void Raise(IEvent evt)
16 | {
17 | var triggerType = typeof(ITriggerEvent<>).MakeGenericType(evt.GetType());
18 | dynamic trigger = _container.GetInstance(triggerType);
19 | trigger.Trigger((dynamic)evt);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ScaffoldR/ScaffoldR.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $title$
7 | $author$
8 | $author$
9 | https://github.com/hartmanns/ScaffoldR
10 | https://github.com/hartmanns/ScaffoldR
11 | http://scaffoldr.hartmanns.io/nuget/nuget-icon.png
12 | false
13 | $description$
14 | Copyright 2015
15 | scaffoldr infrastructure scaffolder cqrs inversion dependency injection
16 |
17 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Entities/IEntityReader.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace ScaffoldR.Core.Entities
4 | {
5 | ///
6 | /// Inform an underlying data store to return a set of read-only entity instances.
7 | ///
8 | /// The entity type to return read-only entity instances of.
9 | public interface IEntityReader where TEntity : Entity
10 | {
11 | ///
12 | /// Inform an underlying data store to return a set of read-only entity instances.
13 | ///
14 | /// IQueryable for set of read-only TEntity instances from an underlying data store.
15 | IQueryable Query();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/IPackageScaffoldR.cs:
--------------------------------------------------------------------------------
1 | using SimpleInjector;
2 |
3 | namespace ScaffoldR.Infrastructure.CompositionRoot
4 | {
5 | ///
6 | /// A ScaffoldR encapsules the ScaffoldR infrastructure and registeres the services in the Simple Injector container.
7 | ///
8 | public interface IPackageScaffoldR
9 | {
10 | ///
11 | /// Registers the services in the
12 | ///
13 | /// The Simple Injector container
14 | /// The Composition Root Settings
15 | void RegisterServices(Container container, CompositionRootSettings settings);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Views/Fakes/FakeViewModel.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Views;
2 |
3 | namespace ScaffoldR.Tests.Infrastructure.Views.Fakes
4 | {
5 | public class FakeViewModel : IViewModel
6 | {
7 | public string ReturnType { get; set; }
8 | }
9 |
10 | public class HandleFakeViewModel : IHandleViewModel
11 | {
12 | public FakeViewModel Handle()
13 | {
14 | return new FakeViewModel {ReturnType = "faked"};
15 | }
16 | }
17 |
18 | public class HandleFakeViewModelWithArgument : IHandleViewModel
19 | {
20 | public FakeViewModel Handle(string input)
21 | {
22 | return new FakeViewModel { ReturnType = input };
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Queries/IHandleQuery.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Queries
2 | {
3 | ///
4 | /// Handles the with the return type of .
5 | ///
6 | /// The query.
7 | /// The return type of the .
8 | public interface IHandleQuery where TQuery : IQuery
9 | {
10 | ///
11 | /// Handles the .
12 | ///
13 | /// The query.
14 | /// Returns the .
15 | TResult Handle(TQuery query);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Commands/CommandProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using ScaffoldR.Core.Commands;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.Commands
6 | {
7 | internal sealed class CommandProcessor : IProcessCommands
8 | {
9 | private readonly Container _container;
10 |
11 | public CommandProcessor(Container container)
12 | {
13 | _container = container;
14 | }
15 |
16 | [DebuggerStepThrough]
17 | public void Execute(ICommand command)
18 | {
19 | var handlerType = typeof(IHandleCommand<>).MakeGenericType(command.GetType());
20 | dynamic handler = _container.GetInstance(handlerType);
21 |
22 | handler.Handle((dynamic)command);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Queries/QueryProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using ScaffoldR.Core.Queries;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.Queries
6 | {
7 | internal sealed class QueryProcessor : IProcessQueries
8 | {
9 | private readonly Container _container;
10 |
11 | public QueryProcessor(Container container)
12 | {
13 | _container = container;
14 | }
15 |
16 | [DebuggerStepThrough]
17 | public TResult Execute(IQuery query)
18 | {
19 | var handlerType = typeof(IHandleQuery<,>).MakeGenericType(query.GetType(), typeof(TResult));
20 | dynamic handler = _container.GetInstance(handlerType);
21 | return handler.Handle((dynamic)query);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Queries/Fakes/FakeQueryWithValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using ScaffoldR.Core.Queries;
3 |
4 | namespace ScaffoldR.Tests.Infrastructure.Queries.Fakes
5 | {
6 | public class FakeQueryWithValidator : IQuery
7 | {
8 | public string InputValue { get; set; }
9 | }
10 |
11 | public class ValidateFakeQueryWithValidator: AbstractValidator
12 | {
13 | public ValidateFakeQueryWithValidator()
14 | {
15 | RuleFor(x => x.InputValue).NotEmpty();
16 | }
17 | }
18 |
19 | public class HandleFakeQueryWithValidator : IHandleQuery
20 | {
21 | public string Handle(FakeQueryWithValidator query)
22 | {
23 | return "faked";
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Entities/EntityFrameworkUnitOfWorkTests.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using ScaffoldR.EntityFramework.Entities;
3 | using ScaffoldR.EntityFramework.Tests.Fakes;
4 | using ScaffoldR.EntityFramework.Tests.Helpers;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.EntityFramework.Tests.Entities
8 | {
9 | public class EntityFrameworkUnitOfWorkTests
10 | {
11 | [Fact]
12 | public void Execute_InvokesSaveChanges_OnDbContext()
13 | {
14 | var context = EntityFrameworkMockHelper.GetMockContext();
15 | context.Setup(x => x.SaveChanges()).Returns(1);
16 |
17 | var unitOfWork = new EntityFrameworkUnitOfWork(() => context.Object);
18 | unitOfWork.Execute();
19 |
20 | context.Verify(x => x.SaveChanges(), Times.Once);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Commands/CommandNotNullDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Commands;
4 |
5 | namespace ScaffoldR.Infrastructure.Commands
6 | {
7 | internal sealed class CommandNotNullDecorator : IHandleCommand where TCommand : ICommand
8 | {
9 | private readonly Func> _handlerFactory;
10 |
11 | public CommandNotNullDecorator(Func> handlerFactory)
12 | {
13 | _handlerFactory = handlerFactory;
14 | }
15 |
16 | [DebuggerStepThrough]
17 | public void Handle(TCommand command)
18 | {
19 | if (Equals(command, null)) throw new ArgumentNullException("command");
20 |
21 | _handlerFactory().Handle(command);
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Queries/QueryNotNullDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Queries;
4 |
5 | namespace ScaffoldR.Infrastructure.Queries
6 | {
7 | internal sealed class QueryNotNullDecorator : IHandleQuery where TQuery : IQuery
8 | {
9 | private readonly Func> _handlerFactory;
10 |
11 | public QueryNotNullDecorator(Func> handlerFactory)
12 | {
13 | _handlerFactory = handlerFactory;
14 | }
15 |
16 | [DebuggerStepThrough]
17 | public TResult Handle(TQuery query)
18 | {
19 | if (Equals(query, null)) throw new ArgumentNullException(nameof(query));
20 | return _handlerFactory().Handle(query);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Views/ViewModelWithArgumentNotNullDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ScaffoldR.Core.Views;
3 |
4 | namespace ScaffoldR.Infrastructure.Views
5 | {
6 | internal sealed class ViewModelWithArgumentNotNullDecorator : IHandleViewModel where TViewModel : IViewModel
7 | {
8 | private readonly Func> _handlerFactory;
9 |
10 | public ViewModelWithArgumentNotNullDecorator(Func> handlerFactory)
11 | {
12 | _handlerFactory = handlerFactory;
13 | }
14 |
15 | public TViewModel Handle(TInput input)
16 | {
17 | if (Equals(input, null)) throw new ArgumentNullException(nameof(input));
18 | return _handlerFactory().Handle(input);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/ScaffoldR.EntityFramework.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $title$
7 | $author$
8 | $author$
9 | https://github.com/hartmanns/ScaffoldR
10 | https://github.com/hartmanns/ScaffoldR
11 | http://scaffoldr.hartmanns.io/nuget/nuget-icon.png
12 | false
13 | $description$
14 | Copyright 2015
15 | scaffoldr infrastructure scaffolder cqrs inversion dependency injection entity framework
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Entities/EntityWriterAdapter.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Entities;
2 |
3 | namespace ScaffoldR.EntityFramework.Entities
4 | {
5 | internal sealed class EntityWriterAdapter : IEntityWriter where TEntity : Entity
6 | {
7 | private readonly EntityFrameworkRepository _repository;
8 |
9 | public EntityWriterAdapter(EntityFrameworkRepository repository)
10 | {
11 | _repository = repository;
12 | }
13 |
14 | public TEntity Get(object primaryKey)
15 | {
16 | return _repository.Get(primaryKey);
17 | }
18 |
19 | public void Save(TEntity entity)
20 | {
21 | _repository.Save(entity);
22 | }
23 |
24 | public void Delete(TEntity entity)
25 | {
26 | _repository.Delete(entity);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Fakes/FakeDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Entity;
3 |
4 | namespace ScaffoldR.EntityFramework.Tests.Fakes
5 | {
6 | public class FakeDbContext : DbContext
7 | {
8 | ///
9 | /// This field is for supporting AppVeyor CI configuration
10 | ///
11 | private static readonly string DefaultConnectionString =
12 | Environment.GetEnvironmentVariable("DefaultConnectionString") ??
13 | @"Data Source=.\SQLEXPRESS;Initial Catalog=ScaffoldR_IntegrationTests;Integrated Security=True;MultipleActiveResultSets=True;";
14 |
15 | public virtual DbSet FakeCustomers { get; set; }
16 |
17 | public FakeDbContext() : base(DefaultConnectionString)
18 | {
19 | Database.SetInitializer(new FakeDbContextInitializer());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/Fakes/FakeCommandWithValidator.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using ScaffoldR.Core.Commands;
3 |
4 | namespace ScaffoldR.Tests.Infrastructure.Commands.Fakes
5 | {
6 | public class FakeCommandWithValidator : ICommand
7 | {
8 | public string InputValue { get; set; }
9 | public string ReturnValue { get; internal set; }
10 | }
11 |
12 | public class ValidateFakeCommandWithValidator : AbstractValidator
13 | {
14 | public ValidateFakeCommandWithValidator()
15 | {
16 | RuleFor(x => x.InputValue).NotEmpty();
17 | }
18 | }
19 |
20 | public class HandleFakeCommandWithValidator : IHandleCommand
21 | {
22 | public void Handle(FakeCommandWithValidator command)
23 | {
24 | command.ReturnValue = "faked";
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Queries/QueryProcessorTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Queries;
2 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
3 | using ScaffoldR.Tests.Infrastructure.Queries.Fakes;
4 | using Xunit;
5 |
6 | namespace ScaffoldR.Tests.Infrastructure.Queries
7 | {
8 | [Collection("Simple Injector Tests")]
9 | public class QueryProcessorTests
10 | {
11 | private readonly CompositionRootFixture _fixture;
12 |
13 | public QueryProcessorTests(CompositionRootFixture fixture)
14 | {
15 | _fixture = fixture;
16 | }
17 |
18 | [Fact]
19 | public void Execute_InvokesQueryHandler_UsingContainerForResolution()
20 | {
21 | var queries = _fixture.Container.GetInstance();
22 | var result = queries.Execute(new FakeQueryWithoutValidator());
23 |
24 | Assert.Equal("faked", result);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/EventPackage.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Events;
2 | using ScaffoldR.Infrastructure.Events;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
6 | {
7 | internal sealed class EventPackage : IPackageScaffoldR
8 | {
9 | public void RegisterServices(Container container, CompositionRootSettings settings)
10 | {
11 | if (settings.EventAssemblies == null) return;
12 |
13 | container.RegisterSingleton();
14 |
15 | container.RegisterCollection(typeof(IHandleEvent<>), settings.EventAssemblies);
16 |
17 | container.Register(typeof(ITriggerEvent<>), typeof(MultipleDispatchEventTrigger<>));
18 |
19 | container.RegisterDecorator(
20 | typeof(ITriggerEvent<>),
21 | typeof(TriggerEventWhenHandlersExistDecorator<>)
22 | );
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/CommandProcessorTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Commands;
2 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using Xunit;
5 |
6 | namespace ScaffoldR.Tests.Infrastructure.Commands
7 | {
8 | [Collection("Simple Injector Tests")]
9 | public class CommandProcessorTests
10 | {
11 | private readonly CompositionRootFixture _fixture;
12 |
13 | public CommandProcessorTests(CompositionRootFixture fixture)
14 | {
15 | _fixture = fixture;
16 | }
17 |
18 | [Fact]
19 | public void Execute_InvokesCommandHandler_UsingContainerForResolution()
20 | {
21 | var commands = _fixture.Container.GetInstance();
22 | var command = new FakeCommandWithoutValidator();
23 | commands.Execute(command);
24 |
25 | Assert.Equal("faked", command.ReturnValue);
26 |
27 | }
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/FluentValidation/NerveFrameworkValidatorFactoryTests.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using Xunit;
5 |
6 | namespace ScaffoldR.Tests.Infrastructure.FluentValidation
7 | {
8 | [Collection("Simple Injector Tests")]
9 | public class ScaffoldRValidatorFactoryTests
10 | {
11 | private readonly CompositionRootFixture _fixture;
12 |
13 | public ScaffoldRValidatorFactoryTests(CompositionRootFixture fixture)
14 | {
15 | _fixture = fixture;
16 | }
17 |
18 | [Fact]
19 | public void CreateInstance_CanCreateInstanceOf_ValidateNothingValidator()
20 | {
21 | var validator = _fixture.Container.GetInstance(typeof(IValidator));
22 |
23 | Assert.NotNull(validator);
24 | Assert.IsType(validator);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/FluentValidation/ValidateCommandDecorator.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using FluentValidation;
3 | using ScaffoldR.Core.Commands;
4 | using ScaffoldR.Core.Transactions;
5 |
6 | namespace ScaffoldR.Infrastructure.FluentValidation
7 | {
8 | internal sealed class ValidateCommandDecorator : IHandleCommand where TCommand : ICommand
9 | {
10 | private readonly IHandleCommand _decorated;
11 | private readonly IValidator _validator;
12 |
13 | public ValidateCommandDecorator(IHandleCommand decorated
14 | , IValidator validator
15 | )
16 | {
17 | _decorated = decorated;
18 | _validator = validator;
19 | }
20 |
21 | [DebuggerStepThrough]
22 | public void Handle(TCommand command)
23 | {
24 | _validator.ValidateAndThrow(command);
25 |
26 | _decorated.Handle(command);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/FluentValidation/ValidateQueryDecorator.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using FluentValidation;
3 | using ScaffoldR.Core.Queries;
4 | using ScaffoldR.Core.Transactions;
5 |
6 | namespace ScaffoldR.Infrastructure.FluentValidation
7 | {
8 | internal sealed class ValidateQueryDecorator : IHandleQuery where TQuery : IQuery
9 | {
10 | private readonly IHandleQuery _decorated;
11 | private readonly IValidator _validator;
12 |
13 | public ValidateQueryDecorator(IHandleQuery decorated
14 | , IValidator validator
15 | )
16 | {
17 | _decorated = decorated;
18 | _validator = validator;
19 | }
20 |
21 | [DebuggerStepThrough]
22 | public TResult Handle(TQuery query)
23 | {
24 | _validator.ValidateAndThrow(query);
25 |
26 | return _decorated.Handle(query);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Events/EventProcessorTests.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using ScaffoldR.Core.Events;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using ScaffoldR.Tests.Infrastructure.Events.Fakes;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.Tests.Infrastructure.Events
8 | {
9 | [Collection("Simple Injector Tests")]
10 | public class EventProcessorTests
11 | {
12 | private readonly CompositionRootFixture _fixture;
13 |
14 | public EventProcessorTests(CompositionRootFixture fixture)
15 | {
16 | _fixture = fixture;
17 | }
18 |
19 | [Fact]
20 | public void Execute_InvokesEventHandler_UsingContainerForResolution()
21 | {
22 | var events = _fixture.Container.GetInstance();
23 | var @event = new FakeEventWithoutValidation();
24 | events.Raise(@event);
25 | Thread.Sleep(1000); // :-(
26 | Assert.Equal("faked", @event.ReturnValue);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Events/MultipleDispatchEventTrigger.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using ScaffoldR.Core.Events;
4 |
5 | namespace ScaffoldR.Infrastructure.Events
6 | {
7 | ///
8 | /// Fires multiple dispatch event triggers
9 | ///
10 | ///
11 | internal sealed class MultipleDispatchEventTrigger : ITriggerEvent where TEvent : IEvent
12 | {
13 | private readonly IEnumerable> _handleEvents;
14 |
15 | public MultipleDispatchEventTrigger(IEnumerable> handleEvents)
16 | {
17 | _handleEvents = handleEvents;
18 | }
19 |
20 | public void Trigger(TEvent e)
21 | {
22 | if (_handleEvents == null || !_handleEvents.Any()) return;
23 |
24 | foreach (var handler in _handleEvents)
25 | {
26 | handler.Handle(e);
27 | }
28 | }
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/CompositionRoot/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using SimpleInjector.Diagnostics;
3 | using Xunit;
4 |
5 | namespace ScaffoldR.Tests.Infrastructure.CompositionRoot
6 | {
7 | [Collection("Simple Injector Tests")]
8 | public class CompositionRootTests
9 | {
10 | private readonly CompositionRootFixture _fixture;
11 |
12 | public CompositionRootTests(CompositionRootFixture fixture)
13 | {
14 | _fixture = fixture;
15 | }
16 |
17 | [Fact]
18 | public void CompositionRoot_ComposesVerifiedRoot_WithoutDiagnosticsWarnings()
19 | {
20 | _fixture.Container.Verify();
21 | var results = Analyzer.Analyze(_fixture.Container);
22 |
23 | Assert.False(results.Any());
24 | }
25 |
26 | [Fact]
27 | public void CompositionRoot_AllowsOverridingRegistrations()
28 | {
29 | Assert.False(_fixture.Container.Options.AllowOverridingRegistrations);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/CompositionRoot/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using SimpleInjector.Diagnostics;
3 | using Xunit;
4 |
5 | namespace ScaffoldR.EntityFramework.Tests.CompositionRoot
6 | {
7 | [Collection("Simple Injector Tests")]
8 | public class CompositionRootTests
9 | {
10 | private readonly CompositionRootFixture _fixture;
11 |
12 | public CompositionRootTests(CompositionRootFixture fixture)
13 | {
14 | _fixture = fixture;
15 | }
16 |
17 | [Fact]
18 | public void CompositionRoot_ComposesVerifiedRoot_WithoutDiagnosticsWarnings()
19 | {
20 | _fixture.Container.Verify();
21 | var results = Analyzer.Analyze(_fixture.Container);
22 |
23 | Assert.False(results.Any());
24 | }
25 |
26 | [Fact]
27 | public void CompositionRoot_AllowsOverridingRegistrations()
28 | {
29 | Assert.False(_fixture.Container.Options.AllowOverridingRegistrations);
30 | }
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Views/ViewModelProcessor.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Views;
2 | using SimpleInjector;
3 |
4 | namespace ScaffoldR.Infrastructure.Views
5 | {
6 | internal sealed class ViewModelProcessor : IProcessViewModels
7 | {
8 | private readonly Container _container;
9 |
10 | public ViewModelProcessor(Container container)
11 | {
12 | _container = container;
13 | }
14 |
15 | public TViewModel Create() where TViewModel : IViewModel
16 | {
17 | var handler = _container.GetInstance>();
18 | return handler.Handle();
19 | }
20 |
21 | public TViewModel Create(TInput input) where TViewModel : IViewModel
22 | {
23 | var handlerType = typeof(IHandleViewModel<,>).MakeGenericType(typeof(TViewModel), typeof(TInput));
24 | dynamic handler = _container.GetInstance(handlerType);
25 | return handler.Handle((dynamic)input);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Views/IProcessViewModels.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Views
2 | {
3 | ///
4 | /// Processes and creates view models.
5 | ///
6 | public interface IProcessViewModels
7 | {
8 | ///
9 | /// Creates the .
10 | ///
11 | /// The view model
12 | TViewModel Create() where TViewModel : IViewModel;
13 |
14 | ///
15 | /// Create the with an argument of type
16 | ///
17 | /// The view model which should be constructed
18 | /// The type of argument for the view model
19 | /// The argument for the view model
20 | /// The view model
21 | TViewModel Create(TInput input) where TViewModel : IViewModel;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/TransactionPackage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ScaffoldR.Core.Transactions;
3 | using ScaffoldR.Infrastructure.Transactions;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
7 | {
8 | internal sealed class TransactionPackage : IPackageScaffoldR
9 | {
10 | public void RegisterServices(Container container, CompositionRootSettings settings)
11 | {
12 | // When there is no explicit transaction processor registered, give it an empty one.
13 | // The interfaces is most likely to wired up in sub packages for e.g. saving changes to a context.
14 | var registration = new Lazy(() => Lifestyle.Singleton.CreateRegistration(container));
15 | container.ResolveUnregisteredType += (sender, e) => {
16 | if (e.UnregisteredServiceType == typeof(IProcessTransactions)) e.Register(registration.Value);
17 | };
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Validation/IProcessValidation.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation.Results;
2 | using ScaffoldR.Core.Commands;
3 | using ScaffoldR.Core.Queries;
4 | using ScaffoldR.Core.Transactions;
5 |
6 | namespace ScaffoldR.Core.Validation
7 | {
8 | ///
9 | /// Processes command and query validation.
10 | ///
11 | public interface IProcessValidation
12 | {
13 | ///
14 | /// Validates if a command is valid for execution.
15 | ///
16 | /// The command which should be validated.
17 | /// The of the command.
18 | ValidationResult Validate(ICommand command);
19 |
20 | ///
21 | /// Validates if a query is valid for execution.
22 | ///
23 | /// The query which should be validated.
24 | /// The of the query
25 | ValidationResult Validate(IQuery query);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Queries/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Queries;
2 | using ScaffoldR.Infrastructure.Queries;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using SimpleInjector;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.Tests.Infrastructure.Queries
8 | {
9 | [Collection("Simple Injector Tests")]
10 | public class CompositionRootTests
11 | {
12 | private readonly CompositionRootFixture _fixture;
13 |
14 | public CompositionRootTests(CompositionRootFixture fixture)
15 | {
16 | _fixture = fixture;
17 | }
18 |
19 | [Fact]
20 | public void RegistersIProcessQueries_UsingQueryProcessor_AsSingleton()
21 | {
22 | var instance = _fixture.Container.GetInstance();
23 | var registration = _fixture.Container.GetRegistration(typeof (IProcessQueries));
24 |
25 | Assert.NotNull(instance);
26 | Assert.IsType(instance);
27 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Queries/QueryLifetimeScopeDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Queries;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.Queries
7 | {
8 | internal sealed class QueryLifetimeScopeDecorator : IHandleQuery where TQuery : IQuery
9 | {
10 | private readonly Container _container;
11 | private readonly Func> _handlerFactory;
12 |
13 | public QueryLifetimeScopeDecorator(Container container, Func> handlerFactory)
14 | {
15 | _container = container;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | [DebuggerStepThrough]
20 | public TResult Handle(TQuery query)
21 | {
22 | if (_container.GetCurrentLifetimeScope() != null)
23 | return _handlerFactory().Handle(query);
24 | using (_container.BeginLifetimeScope())
25 | return _handlerFactory().Handle(query);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Commands;
2 | using ScaffoldR.Infrastructure.Commands;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using SimpleInjector;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.Tests.Infrastructure.Commands
8 | {
9 | [Collection("Simple Injector Tests")]
10 | public class CompositionRootTests
11 | {
12 | private readonly CompositionRootFixture _fixture;
13 |
14 | public CompositionRootTests(CompositionRootFixture fixture)
15 | {
16 | _fixture = fixture;
17 | }
18 |
19 | [Fact]
20 | public void RegistersIProcessCommands_UsingCommandProcessor_AsSingleton()
21 | {
22 | var instance = _fixture.Container.GetInstance();
23 | var registration = _fixture.Container.GetRegistration(typeof (IProcessCommands));
24 |
25 | Assert.NotNull(instance);
26 | Assert.IsType(instance);
27 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
28 | }
29 |
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Entities/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Transactions;
2 | using ScaffoldR.Infrastructure.Transactions;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using SimpleInjector;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.Tests.Infrastructure.Entities
8 | {
9 | [Collection("Simple Injector Tests")]
10 | public class CompositionRootTests
11 | {
12 | private readonly CompositionRootFixture _fixture;
13 |
14 | public CompositionRootTests(CompositionRootFixture fixture)
15 | {
16 | _fixture = fixture;
17 | }
18 |
19 | [Fact]
20 | public void RegistersEmptyProcessTransation_AsSingleton_WhenIProcessTransactionsIsNotRegisted()
21 | {
22 | var instance = _fixture.Container.GetInstance();
23 | var registration = _fixture.Container.GetRegistration(typeof (IProcessTransactions));
24 |
25 | Assert.NotNull(instance);
26 | Assert.IsType(instance);
27 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Views/ViewModelLifetimeScopeDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Views;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.Views
7 | {
8 | internal sealed class ViewModelLifetimeScopeDecorator : IHandleViewModel where TViewModel : IViewModel
9 | {
10 | private readonly Container _container;
11 | private readonly Func> _handlerFactory;
12 |
13 | public ViewModelLifetimeScopeDecorator(Container container, Func> handlerFactory)
14 | {
15 | _container = container;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | [DebuggerStepThrough]
20 | public TViewModel Handle()
21 | {
22 | if (_container.GetCurrentLifetimeScope() != null)
23 | {
24 | return _handlerFactory().Handle();
25 | }
26 |
27 | using (_container.BeginLifetimeScope())
28 | {
29 | return _handlerFactory().Handle();
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Commands/CommandTransactionDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ScaffoldR.Core.Commands;
3 | using ScaffoldR.Core.Extensions;
4 | using ScaffoldR.Core.Transactions;
5 |
6 | namespace ScaffoldR.Infrastructure.Commands
7 | {
8 | internal sealed class CommandTransactionDecorator : IHandleCommand where TCommand : ICommand
9 | {
10 | private readonly IProcessTransactions _transactions;
11 | private readonly Func> _handlerFactory;
12 |
13 | public CommandTransactionDecorator(IProcessTransactions transactions, Func> handlerFactory)
14 | {
15 | _transactions = transactions;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | public void Handle(TCommand command)
20 | {
21 | var handler = _handlerFactory();
22 | handler.Handle(command);
23 |
24 | var attribute = handler.GetType().GetRuntimeAddedAttribute();
25 | if (attribute != null)
26 | {
27 | _transactions.Execute();
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Commands/CommandEventProcessingDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ScaffoldR.Core.Commands;
3 | using ScaffoldR.Core.Events;
4 | using ScaffoldR.Core.Extensions;
5 |
6 | namespace ScaffoldR.Infrastructure.Commands
7 | {
8 | internal sealed class CommandEventProcessingDecorator : IHandleCommand where TCommand : ICommand
9 | {
10 | private readonly IProcessEvents _events;
11 | private readonly Func> _handlerFactory;
12 |
13 | public CommandEventProcessingDecorator(IProcessEvents events, Func> handlerFactory)
14 | {
15 | _events = events;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | public void Handle(TCommand command)
20 | {
21 | var handler = _handlerFactory();
22 | handler.Handle(command);
23 |
24 | var attribute = handler.GetType().GetRuntimeAddedAttribute();
25 | if (attribute != null && attribute.Enabled)
26 | {
27 | _events.Raise(command);
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Fakes/FakeDbContextInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data.Entity;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ScaffoldR.EntityFramework.Tests.Fakes
9 | {
10 | public class FakeDbContextInitializer : DropCreateDatabaseAlways
11 | {
12 | protected override void Seed(FakeDbContext context)
13 | {
14 | var customers = new List
15 | {
16 | new FakeCustomer
17 | {
18 | Id = 1,
19 | FirstName = "John",
20 | LastName = "Doe"
21 | },
22 | new FakeCustomer
23 | {
24 | Id = 2,
25 | FirstName = "John",
26 | LastName = "Smith"
27 | }
28 | };
29 |
30 | foreach (var customer in customers)
31 | {
32 | context.FakeCustomers.Add(customer);
33 | }
34 |
35 | base.Seed(context);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/ValidationPackage.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using ScaffoldR.Core.Validation;
3 | using ScaffoldR.Infrastructure.FluentValidation;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
7 | {
8 | internal sealed class ValidationPackage : IPackageScaffoldR
9 | {
10 | public void RegisterServices(Container container, CompositionRootSettings settings)
11 | {
12 | if (settings.FluentValidationAssemblies == null) return;
13 |
14 | ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;
15 |
16 | container.RegisterSingleton();
17 | container.RegisterSingleton();
18 |
19 | container.Register(typeof(IValidator<>), settings.FluentValidationAssemblies);
20 |
21 | // Add unregistered type resolution for objects missing an IValidator
22 | container.RegisterConditional(typeof(IValidator<>), typeof(ValidateNothingDecorator<>), Lifestyle.Singleton, context => !context.Handled);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Commands/CommandLifetimeScopeDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Commands;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.Commands
7 | {
8 | internal sealed class CommandLifetimeScopeDecorator : IHandleCommand where TCommand : ICommand
9 | {
10 | private readonly Container _container;
11 | private readonly Func> _handlerFactory;
12 |
13 | public CommandLifetimeScopeDecorator(Container container, Func> handlerFactory)
14 | {
15 | _container = container;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | [DebuggerStepThrough]
20 | public void Handle(TCommand command)
21 | {
22 | if (_container.GetCurrentLifetimeScope() != null)
23 | {
24 | _handlerFactory().Handle(command);
25 | }
26 | else
27 | {
28 | using (_container.BeginLifetimeScope())
29 | {
30 | _handlerFactory().Handle(command);
31 | }
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Views/ViewModelWithArgumentLifetimeScopeDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Views;
4 | using SimpleInjector;
5 |
6 | namespace ScaffoldR.Infrastructure.Views
7 | {
8 | internal sealed class ViewModelWithArgumentLifetimeScopeDecorator : IHandleViewModel where TViewModel : IViewModel
9 | {
10 | private readonly Container _container;
11 | private readonly Func> _handlerFactory;
12 |
13 | public ViewModelWithArgumentLifetimeScopeDecorator(Container container, Func> handlerFactory)
14 | {
15 | _container = container;
16 | _handlerFactory = handlerFactory;
17 | }
18 |
19 | [DebuggerStepThrough]
20 | public TViewModel Handle(TInput input)
21 | {
22 | if (_container.GetCurrentLifetimeScope() != null)
23 | {
24 | return _handlerFactory().Handle(input);
25 | }
26 |
27 | using (_container.BeginLifetimeScope())
28 | {
29 | return _handlerFactory().Handle(input);
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Views/IHandleViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Views
2 | {
3 | ///
4 | /// Handles the .
5 | ///
6 | /// The view model which should be handled.
7 | public interface IHandleViewModel where TViewModel : IViewModel
8 | {
9 | ///
10 | /// Creates a .
11 | ///
12 | /// An instance of the .
13 | TViewModel Handle();
14 | }
15 |
16 | ///
17 | /// Handles the with the argument of
18 | ///
19 | /// The argument for the view model
20 | /// The view model which should be handled.
21 | public interface IHandleViewModel where TViewModel : IViewModel
22 | {
23 | ///
24 | /// Creates a .
25 | ///
26 | /// An instance of the .
27 | TViewModel Handle(TInput input);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/CompositionRootSettings.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using FluentValidation;
3 | using ScaffoldR.Core.Commands;
4 | using ScaffoldR.Core.Events;
5 | using ScaffoldR.Core.Queries;
6 | using ScaffoldR.Core.Transactions;
7 | using ScaffoldR.Core.Views;
8 |
9 | namespace ScaffoldR.Infrastructure.CompositionRoot
10 | {
11 | ///
12 | /// The main composition settings.
13 | ///
14 | public class CompositionRootSettings
15 | {
16 | ///
17 | /// Where the and are located.
18 | ///
19 | public Assembly[] TransactionAssemblies { get; set; }
20 |
21 | ///
22 | /// Where the are located.
23 | ///
24 | public Assembly[] EventAssemblies { get; set; }
25 |
26 | ///
27 | /// Where the are located
28 | ///
29 | public Assembly[] FluentValidationAssemblies { get; set; }
30 |
31 | ///
32 | /// Where the are located.
33 | ///
34 | public Assembly[] ViewModelAssemblies { get; set; }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/FluentValidation/ValidationProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using FluentValidation;
3 | using FluentValidation.Results;
4 | using ScaffoldR.Core.Commands;
5 | using ScaffoldR.Core.Queries;
6 | using ScaffoldR.Core.Transactions;
7 | using ScaffoldR.Core.Validation;
8 | using SimpleInjector;
9 |
10 | namespace ScaffoldR.Infrastructure.FluentValidation
11 | {
12 | internal sealed class ValidationProcessor : IProcessValidation
13 | {
14 | private readonly Container _container;
15 |
16 | public ValidationProcessor(Container container)
17 | {
18 | _container = container;
19 | }
20 |
21 | [DebuggerStepThrough]
22 | public ValidationResult Validate(IQuery query)
23 | {
24 | var validatedType = typeof(IValidator<>).MakeGenericType(query.GetType());
25 | dynamic validator = _container.GetInstance(validatedType);
26 | return validator.Validate((dynamic)query);
27 | }
28 |
29 | [DebuggerStepThrough]
30 | public ValidationResult Validate(ICommand command)
31 | {
32 | var validatedType = typeof(IValidator<>).MakeGenericType(command.GetType());
33 | dynamic validator = _container.GetInstance(validatedType);
34 | return validator.Validate((dynamic)command);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Queries/QueryEventProcessingDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ScaffoldR.Core.Events;
4 | using ScaffoldR.Core.Extensions;
5 | using ScaffoldR.Core.Queries;
6 |
7 | namespace ScaffoldR.Infrastructure.Queries
8 | {
9 | internal sealed class QueryEventProcessingDecorator : IHandleQuery where TQuery : IQuery
10 | {
11 | private readonly IProcessEvents _events;
12 | private readonly Func> _handlerFactory;
13 |
14 | public QueryEventProcessingDecorator(IProcessEvents events, Func> handlerFactory)
15 | {
16 | _events = events;
17 | _handlerFactory = handlerFactory;
18 | }
19 |
20 | [DebuggerStepThrough]
21 | public TResult Handle(TQuery query)
22 | {
23 | var handler = _handlerFactory();
24 | try
25 | {
26 | return handler.Handle(query);
27 | }
28 | finally
29 | {
30 | var attribute = handler.GetType().GetRuntimeAddedAttribute();
31 | if (attribute != null && attribute.Enabled)
32 | {
33 | _events.Raise(query);
34 | }
35 | }
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/FluentValidation/SimpleInjectorValidatorFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using FluentValidation;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.FluentValidation
6 | {
7 | ///
8 | /// The Fluent Validation Validator Factory. Used to find instances of the 's.
9 | ///
10 | public class SimpleInjectorValidatorFactory : IValidatorFactory
11 | {
12 | private readonly Container _container;
13 |
14 | ///
15 | /// The constructor of the factory.
16 | ///
17 | /// The Simple Injector Container
18 | public SimpleInjectorValidatorFactory(Container container)
19 | {
20 | _container = container;
21 | }
22 |
23 | ///
24 | /// Gets the validator for the specified type.
25 | ///
26 | public IValidator GetValidator()
27 | {
28 | return _container.GetInstance>();
29 | }
30 |
31 | ///
32 | /// Gets the validator for the specified type.
33 | ///
34 | public IValidator GetValidator(Type type)
35 | {
36 | var validator = typeof(IValidator<>).MakeGenericType(type);
37 | return _container.GetInstance(validator) as IValidator;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/CompositionRoot/CompositionRootFixture.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using ScaffoldR.Infrastructure.CompositionRoot;
3 | using SimpleInjector;
4 | using SimpleInjector.Extensions.LifetimeScoping;
5 | using Xunit;
6 |
7 | namespace ScaffoldR.Tests.Infrastructure.CompositionRoot
8 | {
9 | public class CompositionRootFixture
10 | {
11 | public Container Container { get; }
12 |
13 | public CompositionRootFixture()
14 | {
15 | Container = new Container();
16 | Container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();
17 |
18 | var assemblies = new[] { Assembly.GetExecutingAssembly() };
19 |
20 | Container.RegisterScaffoldR(settings =>
21 | {
22 | settings.EventAssemblies = assemblies;
23 | settings.FluentValidationAssemblies = assemblies;
24 | settings.TransactionAssemblies = assemblies;
25 | settings.ViewModelAssemblies = assemblies;
26 | });
27 | }
28 |
29 | }
30 |
31 | [CollectionDefinition("Simple Injector Tests")]
32 | public class SimpleInjectorTests : ICollectionFixture
33 | {
34 | // This class has no code, and is never created. Its purpose is simply
35 | // to be the place to apply [CollectionDefinition] and all the
36 | // ICollectionFixture<> interfaces.
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/ViewModelPackage.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Views;
2 | using ScaffoldR.Infrastructure.Views;
3 | using SimpleInjector;
4 |
5 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
6 | {
7 | internal sealed class ViewModelPackage : IPackageScaffoldR
8 | {
9 | public void RegisterServices(Container container, CompositionRootSettings settings)
10 | {
11 | if (settings.ViewModelAssemblies == null) return;
12 |
13 | container.RegisterSingleton();
14 |
15 | container.Register(typeof(IHandleViewModel<>), settings.ViewModelAssemblies);
16 | container.Register(typeof(IHandleViewModel<,>), settings.ViewModelAssemblies);
17 |
18 | container.RegisterDecorator(
19 | typeof(IHandleViewModel<>),
20 | typeof(ViewModelLifetimeScopeDecorator<>),
21 | Lifestyle.Singleton
22 | );
23 |
24 | container.RegisterDecorator(
25 | typeof(IHandleViewModel<,>),
26 | typeof(ViewModelWithArgumentLifetimeScopeDecorator<,>),
27 | Lifestyle.Singleton
28 | );
29 |
30 | container.RegisterDecorator(
31 | typeof(IHandleViewModel<,>),
32 | typeof(ViewModelWithArgumentNotNullDecorator<,>),
33 | Lifestyle.Singleton
34 | );
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Extensions/ContainerExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Entity;
3 | using ScaffoldR.Core.Entities;
4 | using ScaffoldR.Core.Transactions;
5 | using ScaffoldR.EntityFramework.Entities;
6 | using SimpleInjector;
7 |
8 | namespace ScaffoldR.EntityFramework.Extensions
9 | {
10 | ///
11 | /// Simple Injector container extensions
12 | ///
13 | public static class ContainerExtensions
14 | {
15 | ///
16 | /// Registers the ScaffoldR Entity Framework integration package into the Simple Injector container
17 | ///
18 | /// The DbContext of your application
19 | /// The Simple Injector container object
20 | public static void RegisterEntityFramework(this Container container) where TContext : DbContext
21 | {
22 | if (container == null)
23 | throw new ArgumentNullException(nameof(container));
24 |
25 | container.Register(Lifestyle.Scoped);
26 | container.Register(Lifestyle.Scoped);
27 | container.Register(typeof(EntityFrameworkRepository<>), typeof(EntityFrameworkRepository<>), Lifestyle.Scoped);
28 | container.Register(typeof(IEntityWriter<>), typeof(EntityWriterAdapter<>));
29 | container.Register(typeof(IEntityReader<>), typeof(EntityReaderAdapter<>));
30 | }
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Entities/IEntityWriter.cs:
--------------------------------------------------------------------------------
1 | namespace ScaffoldR.Core.Entities
2 | {
3 | ///
4 | /// Informs an underlying data store to accept sets of writeable entity instances.
5 | ///
6 | ///
7 | public interface IEntityWriter where TEntity : Entity
8 | {
9 | ///
10 | /// Inform an underlying data store to return a single writable entity instance.
11 | ///
12 | /// Primary key value of the entity instance that the underlying data store should return.
13 | /// A single writable entity instance whose primary key matches the argument value(, if one exists in the underlying data store. Otherwise, null.
14 | TEntity Get(object primaryKey);
15 |
16 | ///
17 | /// Inform the underlying data store that a new or existing entity instance's should be saved to a set of entity instances.
18 | ///
19 | /// Entity instance that should be saved to the TEntity set by the underlying data store.
20 | void Save(TEntity entity);
21 |
22 | ///
23 | /// Inform the underlying data store that an existing entity instance should be permanently removed from its set of entity instances.
24 | ///
25 | /// Entity instance that should be permanently removed from the TEntity set by the underlying data store.
26 | void Delete(TEntity entity);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/CompositionRoot/CompositionRootFixture.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using ScaffoldR.EntityFramework.Extensions;
3 | using ScaffoldR.EntityFramework.Tests.Fakes;
4 | using ScaffoldR.Infrastructure.CompositionRoot;
5 | using SimpleInjector;
6 | using SimpleInjector.Extensions.LifetimeScoping;
7 | using Xunit;
8 |
9 | namespace ScaffoldR.EntityFramework.Tests.CompositionRoot
10 | {
11 | public class CompositionRootFixture
12 | {
13 | public Container Container { get; }
14 |
15 | public CompositionRootFixture()
16 | {
17 | Container = new Container();
18 | Container.Options.DefaultScopedLifestyle = new LifetimeScopeLifestyle();
19 |
20 | var assemblies = new[] { Assembly.GetExecutingAssembly() };
21 |
22 | Container.RegisterScaffoldR(settings =>
23 | {
24 | settings.EventAssemblies = assemblies;
25 | settings.FluentValidationAssemblies = assemblies;
26 | settings.TransactionAssemblies = assemblies;
27 | settings.ViewModelAssemblies = assemblies;
28 | });
29 |
30 | // Register Entity Framework
31 | Container.RegisterEntityFramework();
32 | }
33 |
34 | }
35 |
36 | [CollectionDefinition("Simple Injector Tests")]
37 | public class SimpleInjectorTests : ICollectionFixture
38 | {
39 | // This class has no code, and is never created. Its purpose is simply
40 | // to be the place to apply [CollectionDefinition] and all the
41 | // ICollectionFixture<> interfaces.
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ScaffoldR.EntityFramework.Tests")]
9 | [assembly: AssemblyDescription("Integration library for Entity Framework for ScaffoldR")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hartmann Solutions")]
12 | [assembly: AssemblyProduct("ScaffoldR.EntityFramework.Tests")]
13 | [assembly: AssemblyCopyright("Copyright 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("11a3698e-0217-44f0-9236-6abaa2edcc67")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.2.0")]
35 | [assembly: AssemblyVersion("1.0.2.0")]
36 | [assembly: AssemblyFileVersion("1.0.2.0")]
37 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ScaffoldR.EntityFramework")]
9 | [assembly: AssemblyDescription("Integration library for Entity Framework for ScaffoldR")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hartmann Solutions")]
12 | [assembly: AssemblyProduct("ScaffoldR.EntityFramework")]
13 | [assembly: AssemblyCopyright("Copyright 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("62e4e31b-d3ac-4345-9251-a16faf8758f3")]
24 | [assembly: InternalsVisibleTo("ScaffoldR.EntityFramework.Tests")]
25 |
26 | // Version information for an assembly consists of the following four values:
27 | //
28 | // Major Version
29 | // Minor Version
30 | // Build Number
31 | // Revision
32 | //
33 | // You can specify all the values or you can default the Build and Revision Numbers
34 | // by using the '*' as shown below:
35 | // [assembly: AssemblyVersion("1.0.2.0")]
36 | [assembly: AssemblyVersion("1.0.2.0")]
37 | [assembly: AssemblyFileVersion("1.0.2.0")]
38 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ScaffoldR")]
9 | [assembly: AssemblyDescription("ScaffoldR is a SOLID platform for structuring or scaffolding .NET applications. ScaffoldR supports commands, queries, events, repositories and validation with intelligent dispatching via C# generic variance.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hartmann Solutions")]
12 | [assembly: AssemblyProduct("ScaffoldR")]
13 | [assembly: AssemblyCopyright("Copyright 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e4f000b6-1e87-4605-8833-8bb4c8657296")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.2.0")]
35 | [assembly: AssemblyVersion("1.0.2.0")]
36 | [assembly: AssemblyFileVersion("1.0.2.0")]
37 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/Events/TriggerEventWhenHandlersExistDecorator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using ScaffoldR.Core.Events;
5 | using ScaffoldR.Core.Tasks;
6 | using SimpleInjector;
7 |
8 | namespace ScaffoldR.Infrastructure.Events
9 | {
10 | internal sealed class TriggerEventWhenHandlersExistDecorator : ITriggerEvent where TEvent : IEvent
11 | {
12 | private readonly Container _container;
13 | private readonly ITaskFactory _taskFactory;
14 | private readonly Func> _factory;
15 | private readonly IEnumerable> _handleEvents;
16 |
17 | public TriggerEventWhenHandlersExistDecorator(Container container, ITaskFactory taskFactory, Func> factory, IEnumerable> handleEvents)
18 | {
19 | _container = container;
20 | _taskFactory = taskFactory;
21 | _factory = factory;
22 | _handleEvents = handleEvents;
23 | }
24 |
25 | public void Trigger(TEvent evt)
26 | {
27 | if (_handleEvents != null && _handleEvents.Any())
28 | {
29 | _taskFactory.StartTask(() =>
30 | {
31 | if (_container.GetCurrentLifetimeScope() != null)
32 | {
33 | _factory().Trigger(evt);
34 | }
35 | else
36 | {
37 | using (_container.BeginLifetimeScope())
38 | {
39 | _factory().Trigger(evt);
40 | }
41 | }
42 | });
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Events/MultipleDispatchEventTriggerTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Moq;
3 | using ScaffoldR.Core.Events;
4 | using ScaffoldR.Infrastructure.Events;
5 | using ScaffoldR.Tests.Infrastructure.Events.Fakes;
6 | using Xunit;
7 |
8 | namespace ScaffoldR.Tests.Infrastructure.Events
9 | {
10 | public class MultipleDispatchEventTriggerTests
11 | {
12 | [Fact]
13 | public void HandleAllEventHandlers_WhenMultipleEventHandlersExists()
14 | {
15 | var evt = new FakeEventWithoutValidation();
16 | Assert.IsAssignableFrom(evt);
17 |
18 | var handlerOneCallback = string.Empty;
19 | var handlerOne = new Mock>(MockBehavior.Strict);
20 | handlerOne.Setup(x => x.Handle(evt)).Callback(() => handlerOneCallback = "handlerOneCallback");
21 |
22 | var handlerTwoCallback = string.Empty;
23 | var handlerTwo = new Mock>(MockBehavior.Strict);
24 | handlerTwo.Setup(x => x.Handle(evt)).Callback(() => handlerTwoCallback = "handlerTwoCallback");
25 |
26 | var handlers = new List>
27 | {
28 | handlerOne.Object,
29 | handlerTwo.Object
30 | };
31 |
32 | var decorator = new MultipleDispatchEventTrigger(handlers);
33 | decorator.Trigger(evt);
34 |
35 | handlerOne.Verify(x => x.Handle(evt), Times.Once);
36 | handlerTwo.Verify(x => x.Handle(evt), Times.Once);
37 |
38 | Assert.Equal("handlerOneCallback", handlerOneCallback);
39 | Assert.Equal("handlerTwoCallback", handlerTwoCallback);
40 | }
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ScaffoldR")]
9 | [assembly: AssemblyDescription("ScaffoldR is a SOLID platform for structuring or scaffolding .NET applications. ScaffoldR supports commands, queries, events, repositories and validation with intelligent dispatching via C# generic variance.")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hartmann Solutions")]
12 | [assembly: AssemblyProduct("ScaffoldR")]
13 | [assembly: AssemblyCopyright("Copyright 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 | [assembly: InternalsVisibleTo("ScaffoldR.Tests")]
22 | [assembly: InternalsVisibleTo("ScaffoldR.EntityFramework.Tests")]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("60ac8712-cfc6-4065-93a4-7134c74f88f6")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | // You can specify all the values or you can default the Build and Revision Numbers
35 | // by using the '*' as shown below:
36 | // [assembly: AssemblyVersion("1.0.2.0")]
37 | [assembly: AssemblyVersion("1.0.2.0")]
38 | [assembly: AssemblyFileVersion("1.0.2.0")]
39 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Views/ViewModelProcessorTests.cs:
--------------------------------------------------------------------------------
1 | using ScaffoldR.Core.Views;
2 | using ScaffoldR.Infrastructure.Views;
3 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
4 | using ScaffoldR.Tests.Infrastructure.Views.Fakes;
5 | using SimpleInjector;
6 | using Xunit;
7 |
8 | namespace ScaffoldR.Tests.Infrastructure.Views
9 | {
10 | [Collection("Simple Injector Tests")]
11 | public class ViewModelProcessorTests
12 | {
13 | private readonly CompositionRootFixture _fixture;
14 |
15 | public ViewModelProcessorTests(CompositionRootFixture fixture)
16 | {
17 | _fixture = fixture;
18 | }
19 |
20 | [Fact]
21 | public void RegistersIProcessViewModels_UsingViewModelProcessor_AsSingleton()
22 | {
23 | var instance = _fixture.Container.GetInstance();
24 | var registration = _fixture.Container.GetRegistration(typeof(IProcessViewModels));
25 |
26 | Assert.NotNull(instance);
27 | Assert.IsType(instance);
28 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
29 | }
30 |
31 | [Fact]
32 | public void Execute_InvokesViewModelHandler_UsingContainerForResolution()
33 | {
34 | var models = _fixture.Container.GetInstance();
35 | var viewModel = models.Create();
36 |
37 | Assert.Equal("faked", viewModel.ReturnType);
38 | }
39 |
40 | [Fact]
41 | public void Execute_InvokesViewModelWithArgumentHandler_UsingContainerForResolution()
42 | {
43 | var models = _fixture.Container.GetInstance();
44 | var viewModel = models.Create("faked");
45 |
46 | Assert.Equal("faked", viewModel.ReturnType);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/FluentValidation/ValidationProcessorTests.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using FluentValidation;
3 | using ScaffoldR.Core.Validation;
4 | using ScaffoldR.Infrastructure.FluentValidation;
5 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
6 | using ScaffoldR.Tests.Infrastructure.Queries.Fakes;
7 | using SimpleInjector;
8 | using Xunit;
9 |
10 | namespace ScaffoldR.Tests.Infrastructure.FluentValidation
11 | {
12 | public class ValidationProcessorTests
13 | {
14 | [Fact]
15 | public void ValidateCommand_InvokesValidator_UsingContainerForResolution()
16 | {
17 | var container = new Container();
18 | container.RegisterSingleton();
19 | container.Register(typeof(IValidator<>), new[] { Assembly.GetExecutingAssembly() });
20 | container.Verify();
21 |
22 | var validation = container.GetInstance();
23 | var result = validation.Validate(new FakeCommandWithValidator { InputValue = null });
24 |
25 | Assert.False(result.IsValid);
26 | Assert.Equal(1, result.Errors.Count);
27 | }
28 |
29 | [Fact]
30 | public void ValidateQuery_InvokesValidator_UsingContainerForResolution()
31 | {
32 | var container = new Container();
33 | container.RegisterSingleton();
34 | container.Register(typeof(IValidator<>), new[] { Assembly.GetExecutingAssembly() });
35 | container.Verify();
36 |
37 | var validation = container.GetInstance();
38 | var result = validation.Validate(new FakeQueryWithValidator { InputValue = null });
39 |
40 | Assert.False(result.IsValid);
41 | Assert.Equal(1, result.Errors.Count);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/QueryPackage.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using ScaffoldR.Core.Events;
3 | using ScaffoldR.Core.Queries;
4 | using ScaffoldR.Core.Transactions;
5 | using ScaffoldR.Infrastructure.FluentValidation;
6 | using ScaffoldR.Infrastructure.Queries;
7 | using ScaffoldR.Infrastructure.Transactions;
8 | using SimpleInjector;
9 |
10 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
11 | {
12 | internal sealed class QueryPackage : IPackageScaffoldR
13 | {
14 | public void RegisterServices(Container container, CompositionRootSettings settings)
15 | {
16 | if (settings.TransactionAssemblies == null) return;
17 |
18 | container.Register(Lifestyle.Singleton);
19 |
20 | container.Register(typeof (IHandleQuery<,>), settings.TransactionAssemblies);
21 |
22 | container.RegisterDecorator(
23 | typeof(IHandleQuery<,>),
24 | typeof(QueryEventProcessingDecorator<,>),
25 | c =>
26 | {
27 | var attribute = c.ImplementationType.GetCustomAttribute();
28 | return attribute != null && attribute.Enabled;
29 | }
30 | );
31 |
32 | container.RegisterDecorator(
33 | typeof (IHandleQuery<,>),
34 | typeof (ValidateQueryDecorator<,>)
35 | );
36 |
37 | container.RegisterDecorator(
38 | typeof (IHandleQuery<,>),
39 | typeof (QueryLifetimeScopeDecorator<,>),
40 | Lifestyle.Singleton
41 | );
42 |
43 | container.RegisterDecorator(
44 | typeof (IHandleQuery<,>),
45 | typeof (QueryNotNullDecorator<,>),
46 | Lifestyle.Singleton
47 | );
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tools/Build.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [Parameter(Mandatory=$true)]
3 | [string]$version,
4 | [string]$configuration = "Release",
5 | [boolean]$build = $true,
6 | [boolean]$nuspec = $true,
7 | [boolean]$publish = $false,
8 | [boolean]$pack = $false,
9 | [string]$outputFolder = "..\nuget"
10 | )
11 |
12 | # Include build functions
13 | . "./BuildFunctions.ps1"
14 |
15 | # The solution we are building
16 | $solution = "../src/ScaffoldR.sln"
17 |
18 | # Assemblies we are releasing
19 | $assemblies = "../src/ScaffoldR", "../src/ScaffoldR.EntityFramework"
20 |
21 | # Test assemblies
22 | $testAssemblies = "../src/ScaffoldR.Tests", "../src/ScaffoldR.EntityFramework.Tests"
23 |
24 | # Start by changing the assembly version
25 | Write-Host "Changing the assembly versions to '$version'..."
26 | Get-ChildItem ($assemblies + $testAssemblies) -Filter "AssemblyInfo.cs" -Recurse |
27 | % { Update-AssemblyVersion $_.FullName $version }
28 |
29 | # Build the entire solution
30 | if ($build) {
31 | Write-Host "Cleaning and building $solution (Configuration: $configuration)"
32 | New-Solution $solution $configuration
33 | }
34 |
35 | # Change dependency version on all depending assemblies
36 | if ($nuspec) {
37 | Write-Host "Changing the ScaffoldR(s) NuGet Spec version dependencies to '$version'..."
38 | Get-ChildItem $assemblies -Filter "ScaffoldR*.nuspec" -Recurse |
39 | % { Update-NugetSpecDependencyVersion $_.FullName "ScaffoldR" $version }
40 | }
41 |
42 | # Pack the assemblies and move to output folder
43 | if ($pack) {
44 | Write-Host "Packaging projects..."
45 | Get-ChildItem $assemblies -Filter "ScaffoldR*.csproj" -Recurse |
46 | % { Invoke-PackNuget $_.FullName $configuration $outputFolder }
47 | }
48 |
49 | # Publish the assemblies
50 | if ($publish) {
51 | Write-Host "Publishing packages..."
52 | Get-ChildItem $outputFolder -Filter "*$version.nupkg" -Recurse |
53 | % { Publish-NugetPackage $_.FullName }
54 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/Packages/CommandPackage.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using ScaffoldR.Core.Commands;
3 | using ScaffoldR.Core.Events;
4 | using ScaffoldR.Core.Transactions;
5 | using ScaffoldR.Infrastructure.Commands;
6 | using ScaffoldR.Infrastructure.FluentValidation;
7 | using ScaffoldR.Infrastructure.Transactions;
8 | using SimpleInjector;
9 |
10 | namespace ScaffoldR.Infrastructure.CompositionRoot.Packages
11 | {
12 | internal sealed class CommandPackage : IPackageScaffoldR
13 | {
14 | public void RegisterServices(Container container, CompositionRootSettings settings)
15 | {
16 | if (settings.TransactionAssemblies == null) return;
17 |
18 | container.Register(Lifestyle.Singleton);
19 | container.Register(typeof(IHandleCommand<>), settings.TransactionAssemblies);
20 |
21 | container.RegisterDecorator(
22 | typeof(IHandleCommand<>),
23 | typeof(CommandEventProcessingDecorator<>),
24 | c =>
25 | {
26 | var attribute = c.ImplementationType.GetCustomAttribute();
27 | return attribute != null && attribute.Enabled;
28 | }
29 | );
30 |
31 | container.RegisterDecorator(typeof(IHandleCommand<>),
32 | typeof(CommandTransactionDecorator<>),
33 | c => c.ImplementationType.GetCustomAttribute() != null
34 | );
35 |
36 | container.RegisterDecorator(
37 | typeof(IHandleCommand<>),
38 | typeof(ValidateCommandDecorator<>)
39 | );
40 |
41 | container.RegisterDecorator(
42 | typeof(IHandleCommand<>),
43 | typeof(CommandLifetimeScopeDecorator<>),
44 | Lifestyle.Singleton
45 | );
46 |
47 | container.RegisterDecorator(
48 | typeof(IHandleCommand<>),
49 | typeof(CommandNotNullDecorator<>),
50 | Lifestyle.Singleton
51 | );
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework/Entities/EntityFrameworkRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data.Entity;
3 | using System.Linq;
4 | using ScaffoldR.Core.Entities;
5 |
6 | namespace ScaffoldR.EntityFramework.Entities
7 | {
8 | internal sealed class EntityFrameworkRepository : IEntityWriter, IEntityReader where TEntity : Entity
9 | {
10 | private readonly Func _contextProvider;
11 |
12 | public EntityFrameworkRepository(Func contextProvider)
13 | {
14 | _contextProvider = contextProvider;
15 | }
16 |
17 | public void Save(TEntity entity)
18 | {
19 | var context = _contextProvider();
20 | var entry = context.Entry(entity);
21 |
22 | // If it is not tracked by the context, add it to the context
23 | if (entry.State == EntityState.Detached)
24 | {
25 | // This also sets the entity state to added.
26 | context.Set().Add(entity);
27 | }
28 | else
29 | {
30 | // Tells the context that the entity should be updated during saving changes
31 | entry.State = EntityState.Modified;
32 | }
33 | }
34 |
35 | public void Delete(TEntity entity)
36 | {
37 | var context = _contextProvider();
38 | var entry = context.Entry(entity);
39 | if (entry.State != EntityState.Deleted)
40 | {
41 | // This also sets the entity state to Deleted.
42 | context.Set().Remove(entity);
43 | }
44 | }
45 |
46 | public IQueryable Query()
47 | {
48 | return _contextProvider().Set().AsNoTracking();
49 | }
50 |
51 | public TEntity Get(object primaryKey)
52 | {
53 | var context = _contextProvider();
54 | var entity = context.Set().Find(primaryKey);
55 | if (entity == null) return null;
56 |
57 | // We found the entity, set the state to unchanged.
58 | context.Entry(entity).State = EntityState.Unchanged;
59 |
60 | return entity;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/CommandLifetimeScopeDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using ScaffoldR.Core.Commands;
3 | using ScaffoldR.Infrastructure.Commands;
4 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
5 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
6 | using SimpleInjector;
7 | using Xunit;
8 |
9 | namespace ScaffoldR.Tests.Infrastructure.Commands
10 | {
11 | [Collection("Simple Injector Tests")]
12 | public class CommandLifetimeScopeDecoratorTests
13 | {
14 | private readonly CompositionRootFixture _fixture;
15 |
16 | public CommandLifetimeScopeDecoratorTests(CompositionRootFixture fixture)
17 | {
18 | _fixture = fixture;
19 | }
20 |
21 | [Fact]
22 | public void BeginsLifetimeScope_WhenCurrentLifetimeScope_IsNull()
23 | {
24 | var command = new FakeCommandWithValidator();
25 | var decorated = new Mock>(MockBehavior.Strict);
26 | decorated.Setup(x => x.Handle(command));
27 |
28 | var decorator = new CommandLifetimeScopeDecorator(_fixture.Container, () => decorated.Object);
29 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
30 | decorator.Handle(command);
31 |
32 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
33 | decorated.Verify(x => x.Handle(command), Times.Once);
34 | }
35 |
36 | [Fact]
37 | public void UsesCurrentLifetimeScope_WhenCurrentLifetimeScope_IsNotNull()
38 | {
39 | var command = new FakeCommandWithValidator();
40 | var decorated = new Mock>(MockBehavior.Strict);
41 | decorated.Setup(x => x.Handle(command));
42 |
43 | var decorator = new CommandLifetimeScopeDecorator(_fixture.Container, () => decorated.Object);
44 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
45 |
46 | using (_fixture.Container.BeginLifetimeScope())
47 | {
48 | decorator.Handle(command);
49 | }
50 |
51 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
52 |
53 | decorated.Verify(x => x.Handle(command), Times.Once);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Queries/QueryLifetimeScopeDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using Moq;
2 | using ScaffoldR.Core.Queries;
3 | using ScaffoldR.Infrastructure.Queries;
4 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
5 | using ScaffoldR.Tests.Infrastructure.Queries.Fakes;
6 | using SimpleInjector;
7 | using Xunit;
8 |
9 | namespace ScaffoldR.Tests.Infrastructure.Queries
10 | {
11 | [Collection("Simple Injector Tests")]
12 | public class QueryLifetimeScopeDecoratorTests
13 | {
14 | private readonly CompositionRootFixture _fixture;
15 |
16 | public QueryLifetimeScopeDecoratorTests(CompositionRootFixture fixture)
17 | {
18 | _fixture = fixture;
19 | }
20 |
21 | [Fact]
22 | public void BeginsLifetimeScope_WhenCurrentLifetimeScope_IsNull()
23 | {
24 | var query = new FakeQueryWithoutValidator();
25 | var decorated = new Mock>(MockBehavior.Strict);
26 | decorated.Setup(x => x.Handle(query)).Returns("faked");
27 |
28 | var decorator = new QueryLifetimeScopeDecorator(_fixture.Container, () => decorated.Object);
29 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
30 |
31 | var result = decorator.Handle(query);
32 |
33 | Assert.Equal("faked", result);
34 | decorated.Verify(x => x.Handle(query), Times.Once);
35 | }
36 |
37 | [Fact]
38 | public void UsesCurrentLifetimeScope_WhenCurrentLifetimeScope_IsNotNull()
39 | {
40 | var query = new FakeQueryWithoutValidator();
41 | var decorated = new Mock>(MockBehavior.Strict);
42 | decorated.Setup(x => x.Handle(query)).Returns("faked");
43 |
44 | var decorator = new QueryLifetimeScopeDecorator(_fixture.Container, () => decorated.Object);
45 | Assert.Equal(null, _fixture.Container.GetCurrentLifetimeScope());
46 |
47 | string result;
48 | using (_fixture.Container.BeginLifetimeScope())
49 | {
50 | result = decorator.Handle(query);
51 | }
52 |
53 | Assert.Equal("faked", result);
54 |
55 | decorated.Verify(x => x.Handle(query), Times.Once);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/ScaffoldR.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScaffoldR", "ScaffoldR\ScaffoldR.csproj", "{60AC8712-CFC6-4065-93A4-7134C74F88F6}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScaffoldR.Tests", "ScaffoldR.Tests\ScaffoldR.Tests.csproj", "{E4F000B6-1E87-4605-8833-8BB4C8657296}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScaffoldR.EntityFramework", "ScaffoldR.EntityFramework\ScaffoldR.EntityFramework.csproj", "{62E4E31B-D3AC-4345-9251-A16FAF8758F3}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScaffoldR.EntityFramework.Tests", "ScaffoldR.EntityFramework.Tests\ScaffoldR.EntityFramework.Tests.csproj", "{11A3698E-0217-44F0-9236-6ABAA2EDCC67}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {60AC8712-CFC6-4065-93A4-7134C74F88F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {60AC8712-CFC6-4065-93A4-7134C74F88F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {60AC8712-CFC6-4065-93A4-7134C74F88F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {60AC8712-CFC6-4065-93A4-7134C74F88F6}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {E4F000B6-1E87-4605-8833-8BB4C8657296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {E4F000B6-1E87-4605-8833-8BB4C8657296}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {E4F000B6-1E87-4605-8833-8BB4C8657296}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {E4F000B6-1E87-4605-8833-8BB4C8657296}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {62E4E31B-D3AC-4345-9251-A16FAF8758F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {62E4E31B-D3AC-4345-9251-A16FAF8758F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {62E4E31B-D3AC-4345-9251-A16FAF8758F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {62E4E31B-D3AC-4345-9251-A16FAF8758F3}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {11A3698E-0217-44F0-9236-6ABAA2EDCC67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {11A3698E-0217-44F0-9236-6ABAA2EDCC67}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {11A3698E-0217-44F0-9236-6ABAA2EDCC67}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {11A3698E-0217-44F0-9236-6ABAA2EDCC67}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Commands/CommandTransactionDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using Moq;
3 | using ScaffoldR.Core.Commands;
4 | using ScaffoldR.Core.Transactions;
5 | using ScaffoldR.Infrastructure.Commands;
6 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
7 | using Xunit;
8 |
9 | namespace ScaffoldR.Tests.Infrastructure.Commands
10 | {
11 | public class CommandTransactionDecoratorTests
12 | {
13 | [Fact]
14 | public void ExecuteTransaction_WhenCommandHasTransactionalAttribute()
15 | {
16 | var command = new FakeCommandWithoutValidator();
17 | Assert.IsAssignableFrom(command);
18 |
19 | var transactionProcessor = new Mock(MockBehavior.Strict);
20 | transactionProcessor.Setup(x => x.Execute());
21 |
22 | var decorated = new Mock>(MockBehavior.Strict);
23 | var typeDescriptionProvider = TypeDescriptor.AddAttributes(decorated.Object.GetType(), new TransactionalAttribute());
24 | decorated.Setup(x => x.Handle(command));
25 |
26 | var decorator = new CommandTransactionDecorator(transactionProcessor.Object, () => decorated.Object);
27 | decorator.Handle(command);
28 |
29 | decorated.Verify(x => x.Handle(command), Times.Once);
30 | transactionProcessor.Verify(x => x.Execute(), Times.Once);
31 |
32 | // Clean the provider for next test, or else it will fail - very odd.
33 | TypeDescriptor.RemoveProvider(typeDescriptionProvider, decorated.Object.GetType());
34 | }
35 |
36 | [Fact]
37 | public void DoNotExecuteTransaction_WhenCommandDoNotHaveTransactionalAttribute()
38 | {
39 | var command = new FakeCommandWithoutValidator();
40 | Assert.IsAssignableFrom(command);
41 |
42 | var transactionProcessor = new Mock(MockBehavior.Strict);
43 | transactionProcessor.Setup(x => x.Execute());
44 |
45 | var decorated = new Mock>(MockBehavior.Strict);
46 | decorated.Setup(x => x.Handle(command));
47 |
48 | var decorator = new CommandTransactionDecorator(transactionProcessor.Object, () => decorated.Object);
49 | decorator.Handle(command);
50 |
51 | decorated.Verify(x => x.Handle(command), Times.Once);
52 | transactionProcessor.Verify(x => x.Execute(), Times.Never);
53 | }
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/Events/TriggerEventWhenHandlersExistDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Moq;
4 | using ScaffoldR.Core.Events;
5 | using ScaffoldR.Core.Tasks;
6 | using ScaffoldR.Infrastructure.Events;
7 | using ScaffoldR.Tests.Infrastructure.Events.Fakes;
8 | using SimpleInjector;
9 | using Xunit;
10 |
11 | namespace ScaffoldR.Tests.Infrastructure.Events
12 | {
13 | public class TriggerEventWhenHandlersExistDecoratorTests
14 | {
15 | [Fact]
16 | public void TriggerEventHandler_WhenEventHandlersExist()
17 | {
18 | var container = new Container();
19 |
20 | var evt = new FakeEventWithoutValidation();
21 | Assert.IsAssignableFrom(evt);
22 |
23 | var handlers = new List> {new HandleFakeEventWithoutValidation()};
24 |
25 | var decorated = new Mock>(MockBehavior.Strict);
26 | decorated.Setup(x => x.Trigger(evt));
27 |
28 | var taskFactory = new Mock(MockBehavior.Strict);
29 | taskFactory.Setup(factory => factory.StartTask(It.IsAny())).Callback(action => action());
30 |
31 | var decorator = new TriggerEventWhenHandlersExistDecorator(container, taskFactory.Object, () => decorated.Object, handlers);
32 | decorator.Trigger(evt);
33 |
34 | taskFactory.Verify(x => x.StartTask(It.IsAny()), Times.Once);
35 | decorated.Verify(x => x.Trigger(evt), Times.Once);
36 | }
37 |
38 | [Fact]
39 | public void DoNotTriggerEventHandler_WhenEventHandlersDoesNotExist()
40 | {
41 | var container = new Container();
42 |
43 | var evt = new FakeEventWithoutValidation();
44 | Assert.IsAssignableFrom(evt);
45 |
46 | var decorated = new Mock>(MockBehavior.Strict);
47 | decorated.Setup(x => x.Trigger(evt));
48 |
49 | var taskFactory = new Mock(MockBehavior.Strict);
50 | taskFactory.Setup(factory => factory.StartTask(It.IsAny())).Callback(action => action());
51 |
52 | var decorator = new TriggerEventWhenHandlersExistDecorator(container, taskFactory.Object, () => decorated.Object, null);
53 | decorator.Trigger(evt);
54 |
55 | taskFactory.Verify(x => x.StartTask(It.IsAny()), Times.Never);
56 | decorated.Verify(x => x.Trigger(evt), Times.Never);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/FluentValidation/CompositionRootTests.cs:
--------------------------------------------------------------------------------
1 | using FluentValidation;
2 | using ScaffoldR.Core.Validation;
3 | using ScaffoldR.Infrastructure.FluentValidation;
4 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
5 | using ScaffoldR.Tests.Infrastructure.CompositionRoot;
6 | using SimpleInjector;
7 | using Xunit;
8 | using CascadeMode = FluentValidation.CascadeMode;
9 |
10 | namespace ScaffoldR.Tests.Infrastructure.FluentValidation
11 | {
12 | [Collection("Simple Injector Tests")]
13 | public class CompositionRootTests
14 | {
15 | private readonly CompositionRootFixture _fixture;
16 |
17 | public CompositionRootTests(CompositionRootFixture fixture)
18 | {
19 | _fixture = fixture;
20 | }
21 |
22 | [Fact]
23 | public void Sets_ValidatorOptions_CascadeMode_To_StopOnFirstFailure()
24 | {
25 | Assert.Equal(CascadeMode.StopOnFirstFailure, ValidatorOptions.CascadeMode);
26 | }
27 |
28 | [Fact]
29 | public void RegistersIProcessValidation_UsingValidationProcessor_AsSingleton()
30 | {
31 | var instance = _fixture.Container.GetInstance();
32 | var registration = _fixture.Container.GetRegistration(typeof(IProcessValidation));
33 |
34 | Assert.NotNull(instance);
35 | Assert.IsType(instance);
36 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
37 | }
38 |
39 | [Fact]
40 | public void RegistersIValidator_Transiently_UsingOpenGenerics_WhenValidatorExists()
41 | {
42 | var instance = _fixture.Container.GetInstance>();
43 | var registration = _fixture.Container.GetRegistration(typeof(IValidator));
44 |
45 | Assert.NotNull(instance);
46 | Assert.IsType(instance);
47 | Assert.Equal(Lifestyle.Transient, registration.Lifestyle);
48 | }
49 |
50 | [Fact]
51 | public void RegistersIValidator_AsSingleton_UsingValidateNothingDecorator_WhenValidatorDoesNotExist()
52 | {
53 | var instance = _fixture.Container.GetInstance>();
54 | var registration = _fixture.Container.GetRegistration(typeof(IValidator));
55 |
56 | Assert.NotNull(instance);
57 | Assert.IsType>(instance);
58 | Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/FluentValidation/ValidateQueryDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq.Expressions;
3 | using FluentValidation;
4 | using FluentValidation.Results;
5 | using Moq;
6 | using ScaffoldR.Core.Queries;
7 | using ScaffoldR.Core.Transactions;
8 | using ScaffoldR.Infrastructure.FluentValidation;
9 | using ScaffoldR.Tests.Infrastructure.Queries.Fakes;
10 | using Xunit;
11 |
12 | namespace ScaffoldR.Tests.Infrastructure.FluentValidation
13 | {
14 | public class ValidateQueryDecoratorTests
15 | {
16 | [Fact]
17 | public void Handle_ThrowsValidationException_AndDoesNotInvokeDecoratedHandle_WhenValidationFails()
18 | {
19 | var query = new FakeQueryWithoutValidator();
20 | var decorated = new Mock>(MockBehavior.Strict);
21 | var validator = new Mock>(MockBehavior.Strict);
22 | Expression> expectedQuery = x => ReferenceEquals(x, query);
23 |
24 | var expectedResult = new ValidationResult(new[] { new ValidationFailure("Name", "Invalid."), });
25 | validator.Setup(x => x.Validate(It.Is(expectedQuery))).Returns(expectedResult);
26 |
27 | var decorator = new ValidateQueryDecorator(decorated.Object, validator.Object);
28 | var exception = Assert.Throws(() => decorator.Handle(query));
29 |
30 | Assert.NotNull(exception);
31 | validator.Verify(x => x.Validate(It.Is(expectedQuery)), Times.Once);
32 | decorated.Verify(x => x.Handle(It.IsAny()), Times.Never);
33 | }
34 |
35 | [Fact]
36 | public void Handle_InvokesDecoratedHandle_WhenValidationPasses()
37 | {
38 | var query = new FakeQueryWithoutValidator();
39 | var decorated = new Mock>(MockBehavior.Strict);
40 | var validator = new Mock>(MockBehavior.Strict);
41 | var expectedResult = new ValidationResult();
42 | validator.Setup(x => x.Validate(query)).Returns(expectedResult);
43 | decorated.Setup(x => x.Handle(query)).Returns("faked");
44 |
45 | var decorator = new ValidateQueryDecorator(decorated.Object, validator.Object);
46 | var result = decorator.Handle(query);
47 |
48 | Assert.Equal("faked", result);
49 | validator.Verify(x => x.Validate(query), Times.Once);
50 | decorated.Verify(x => x.Handle(query), Times.Once);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Infrastructure/CompositionRoot/ContainerExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Linq.Expressions;
4 | using ScaffoldR.Core.Extensions;
5 | using SimpleInjector;
6 |
7 | namespace ScaffoldR.Infrastructure.CompositionRoot
8 | {
9 | ///
10 | /// The main composition root
11 | ///
12 | public static class ContainerExtensions
13 | {
14 | ///
15 | /// Registers ScaffoldR into the Simple Injector container
16 | ///
17 | /// The Simple Injector Container object
18 | /// The Composition Root Settings
19 | public static void RegisterScaffoldR(this Container container, Action compositionRootSettings)
20 | {
21 | if (container == null)
22 | throw new ArgumentNullException(nameof(container));
23 |
24 | if (compositionRootSettings == null)
25 | throw new ArgumentNullException(nameof(compositionRootSettings));
26 |
27 | var provider = new CompositionRootSettings();
28 | compositionRootSettings(provider);
29 |
30 | container.Options.AllowResolvingFuncFactories();
31 | container.RegisterScaffoldRPackages(provider);
32 | }
33 |
34 | internal static void RegisterScaffoldRPackages(this Container container, CompositionRootSettings settings)
35 | {
36 | var packages = from assembly in AppDomain.CurrentDomain.GetAssemblies()
37 | from type in assembly.GetSafeTypes()
38 | where typeof(IPackageScaffoldR).IsAssignableFrom(type)
39 | where !type.IsAbstract
40 | select (IPackageScaffoldR)Activator.CreateInstance(type);
41 |
42 | packages.ToList().ForEach(p => p.RegisterServices(container, settings));
43 | }
44 |
45 | internal static void AllowResolvingFuncFactories(this ContainerOptions options)
46 | {
47 | options.Container.ResolveUnregisteredType += (s, e) => {
48 | var type = e.UnregisteredServiceType;
49 |
50 | if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>)) return;
51 |
52 | var serviceType = type.GetGenericArguments().First();
53 | var registration = options.Container.GetRegistration(serviceType, true);
54 | var funcType = typeof(Func<>).MakeGenericType(serviceType);
55 |
56 | var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile();
57 | e.Register(Expression.Constant(factoryDelegate));
58 | };
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/ScaffoldR.Tests/Infrastructure/FluentValidation/ValidateCommandDecoratorTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq.Expressions;
3 | using FluentValidation;
4 | using FluentValidation.Results;
5 | using Moq;
6 | using ScaffoldR.Core.Commands;
7 | using ScaffoldR.Core.Transactions;
8 | using ScaffoldR.Infrastructure.FluentValidation;
9 | using ScaffoldR.Tests.Infrastructure.Commands.Fakes;
10 | using Xunit;
11 |
12 | namespace ScaffoldR.Tests.Infrastructure.FluentValidation
13 | {
14 | public class ValidateCommandDecoratorTests
15 | {
16 | [Fact]
17 | public void Handle_ThrowsValidationException_AndDoesNotInvokeDecoratedHandle_WhenValidationFails()
18 | {
19 | var command = new FakeCommandWithValidator();
20 | var decorated = new Mock>(MockBehavior.Strict);
21 | var validator = new Mock>(MockBehavior.Strict);
22 | Expression> expectedCommand = x => ReferenceEquals(x, command);
23 |
24 | var expectedResult = new ValidationResult(new[] { new ValidationFailure("Name", "Invalid.", command.ReturnValue), });
25 | validator.Setup(x => x.Validate(It.Is(expectedCommand))).Returns(expectedResult);
26 | var decorator = new ValidateCommandDecorator(decorated.Object, validator.Object);
27 | var exception = Assert.Throws(() => decorator.Handle(command));
28 |
29 | Assert.NotNull(exception);
30 | validator.Verify(x => x.Validate(It.Is(expectedCommand)), Times.Once);
31 | decorated.Verify(x => x.Handle(It.IsAny()), Times.Never);
32 | }
33 |
34 | [Fact]
35 | public void Handle_InvokesDecoratedHandle_WhenValidationPasses()
36 | {
37 | var command = new FakeCommandWithValidator();
38 | var decorated = new Mock>(MockBehavior.Strict);
39 | var validator = new Mock>(MockBehavior.Strict);
40 | Expression> expectedCommand = x => ReferenceEquals(x, command);
41 |
42 | var expectedResult = new ValidationResult();
43 | validator.Setup(x => x.Validate(It.Is(expectedCommand))).Returns(expectedResult);
44 | decorated.Setup(x => x.Handle(It.Is(expectedCommand)));
45 |
46 | var decorator = new ValidateCommandDecorator(decorated.Object, validator.Object);
47 | decorator.Handle(command);
48 |
49 | validator.Verify(x => x.Validate(It.Is(expectedCommand)), Times.Once);
50 | decorated.Verify(x => x.Handle(It.Is(expectedCommand)), Times.Once);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Extensions/ReflectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace ScaffoldR.Core.Extensions
7 | {
8 | ///
9 | /// Reflection helper extensions
10 | ///
11 | public static class ReflectionExtensions
12 | {
13 | ///
14 | /// Test to see if the type is generically assignable from the another type
15 | ///
16 | /// A class/interface type
17 | /// A class/interface typ
18 | /// True if the type is generically assignable from the other type - otherwise false
19 | public static bool IsGenericallyAssignableFrom(this Type openGeneric, Type closedGeneric)
20 | {
21 | var interfaceTypes = closedGeneric.GetInterfaces();
22 |
23 | if (interfaceTypes.Where(interfaceType => interfaceType.IsGenericType).Any(interfaceType => interfaceType.GetGenericTypeDefinition() == openGeneric))
24 | {
25 | return true;
26 | }
27 |
28 | var baseType = closedGeneric.BaseType;
29 | if (baseType == null) return false;
30 |
31 | return baseType.IsGenericType &&
32 | (baseType.GetGenericTypeDefinition() == openGeneric ||
33 | openGeneric.IsGenericallyAssignableFrom(baseType));
34 | }
35 |
36 | ///
37 | /// Get types of the assembly, but only returns assembly where the types can be loaded.
38 | ///
39 | /// The assembly to look at.
40 | /// An array of types.
41 | public static Type[] GetSafeTypes(this Assembly assembly)
42 | {
43 | try
44 | {
45 | return assembly.GetTypes();
46 | }
47 | catch (ReflectionTypeLoadException ex)
48 | {
49 | return ex.Types;
50 | }
51 | }
52 |
53 | ///
54 | /// Gets a runtime added attribute to a type.
55 | ///
56 | /// The attribute
57 | /// The type.
58 | /// The first attribute or null if none is found.
59 | public static TAttribute GetRuntimeAddedAttribute(this Type type) where TAttribute : Attribute
60 | {
61 | if (type == null) throw new ArgumentNullException(nameof(type));
62 |
63 | var attributes = TypeDescriptor.GetAttributes(type).OfType();
64 | var enumerable = attributes as TAttribute[] ?? attributes.ToArray();
65 | return enumerable.Any() ? enumerable.First() : null;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/tools/BuildFunctions.ps1:
--------------------------------------------------------------------------------
1 | Function New-Solution {
2 |
3 | Param(
4 | [Parameter(Mandatory=$true)]
5 | [string]$solution,
6 | [Parameter(Mandatory=$true)]
7 | [string]$configuration
8 | )
9 |
10 | # Set the path to the .NET folder in order to use "msbuild.exe"
11 | $env:PATH = "C:\Program Files (x86)\MSBuild\14.0\Bin"
12 |
13 | Invoke-Expression "msbuild.exe $solution /nologo /v:m /p:Configuration=$configuration /t:Clean"
14 | Invoke-Expression "msbuild.exe $solution /nologo /v:m /p:Configuration=$configuration /clp:ErrorsOnly"
15 | }
16 |
17 | Function Update-AssemblyVersion() {
18 |
19 | Param(
20 | [Parameter(Mandatory=$true)]
21 | [string]$filePath,
22 | [Parameter(Mandatory=$true)]
23 | [string]$publishVersion
24 | )
25 |
26 | Write-Host ("-- Updating '{0}' to version '{1}'" -f $filePath, $publishVersion)
27 |
28 | $assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
29 | $assemblyVersion = 'AssemblyVersion("' + $publishVersion + '")';
30 | $assemblyFileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
31 | $assemblyFileVersion = 'AssemblyFileVersion("' + $publishVersion + '")';
32 |
33 | (Get-Content $filePath) | ForEach-Object {
34 | % { $_ -Replace $assemblyVersionPattern, $assemblyVersion } |
35 | % { $_ -Replace $assemblyFileVersionPattern, $assemblyFileVersion }
36 | } | Set-Content $filePath
37 | }
38 |
39 | Function Update-NugetSpecDependencyVersion
40 | {
41 | Param
42 | (
43 | [Parameter(Mandatory=$true)]
44 | [string]$filePath,
45 | [Parameter(Mandatory=$true)]
46 | [string]$packageId,
47 | [Parameter(Mandatory=$true)]
48 | [string]$publishVersion
49 | )
50 |
51 | [xml] $toFile = (Get-Content $filePath)
52 |
53 | $nodes = $toFile.SelectNodes("//package/metadata/dependencies/dependency[starts-with(@id, $packageId)]")
54 | foreach ($node in $nodes)
55 | {
56 | Write-Host ("-- Updating '{0}' in '{1}' to version '{2}'" -f $node.id, $filePath, $publishVersion)
57 | $node.version = "[{0}]" -f $publishVersion
58 | }
59 |
60 | $toFile.Save($filePath)
61 |
62 | }
63 |
64 | Function Invoke-PackNuget {
65 |
66 | Param(
67 | [Parameter(Mandatory=$true)]
68 | [string]$project,
69 | [Parameter(Mandatory=$true)]
70 | [string]$configuration,
71 | [Parameter(Mandatory=$true)]
72 | [string]$outputFolder
73 | )
74 |
75 | if (!(Test-Path -Path $outputFolder)) {
76 | New-Item $outputFolder -Type Directory
77 | }
78 |
79 | Write-Host "-- Packaging '$project'"
80 | Invoke-Expression "..\tools\NuGet.exe pack $project -OutputDirectory '$outputFolder' -Prop Configuration=$configuration"
81 | }
82 |
83 | Function Publish-NugetPackage() {
84 |
85 | Param(
86 | [Parameter(Mandatory=$true)]
87 | [string]$package
88 | )
89 |
90 | Write-Host "-- Publishing '$package'"
91 | Invoke-Expression "..\tools\NuGet.exe push $package"
92 |
93 | }
--------------------------------------------------------------------------------
/src/ScaffoldR/Core/Entities/EntityWithId.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ScaffoldR.Core.Entities
4 | {
5 | ///
6 | /// A single entity that can be identified by a primary key.
7 | ///
8 | /// The type of the entity's primary key.
9 | public abstract class EntityWithId : Entity, IEquatable>
10 | {
11 | ///
12 | /// Primary key of this entity.
13 | ///
14 | public TId Id { get; set; }
15 |
16 | ///
17 | /// Get the hash code for this entity instance based on its Id property.
18 | ///
19 | /// The hash code for this object instance based on its Id property.
20 | public override int GetHashCode()
21 | {
22 | return IsTransient(this) ? 0 : Id.GetHashCode();
23 | }
24 |
25 | ///
26 | /// Determine whether this entity is equal to another object.
27 | ///
28 | /// The object to compare to this entity when determining equality.
29 | /// True if the other object is an EntityWithId, both entities are not null or
30 | /// transient, and both entities have the same Id value. Otherwise, false.
31 | public override bool Equals(object other)
32 | {
33 | return Equals(other as EntityWithId);
34 | }
35 |
36 | ///
37 | /// Determine whether this entity is equal to another entity.
38 | ///
39 | /// The entity to compare to this entity when determining equality.
40 | /// True if the other entity is not null, neither entity is transient, and both
41 | /// entities share the same Id value.
42 | public virtual bool Equals(EntityWithId other)
43 | {
44 | // instance is never equal to null
45 | if (other == null) return false;
46 |
47 | // when references are equal, they are the same object
48 | if (ReferenceEquals(this, other)) return true;
49 |
50 | // when either object is transient or the id's are not equal, return false
51 | if (IsTransient(this) || IsTransient(other) || !Equals(Id, other.Id)) return false;
52 |
53 | // when the id's are equal and neither object is transient
54 | // return true when one can be cast to the other
55 | // because this entity could be generated by a proxy
56 | var otherType = other.GetUnproxiedType();
57 | var thisType = GetUnproxiedType();
58 | return thisType.IsAssignableFrom(otherType) || otherType.IsAssignableFrom(thisType);
59 | }
60 |
61 | private static bool IsTransient(EntityWithId obj)
62 | {
63 | // an object is transient when its id is the default (null for strings or 0 for numbers)
64 | return Equals(obj.Id, default(TId));
65 | }
66 |
67 | private Type GetUnproxiedType()
68 | {
69 | return GetType(); // return the unproxied type of the object
70 | }
71 |
72 | }
73 | }
--------------------------------------------------------------------------------
/src/ScaffoldR.EntityFramework.Tests/Entities/EntityFrameworkRepositoryTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Data.Entity;
3 | using System.Data.Entity.Core.Objects.DataClasses;
4 | using System.Linq;
5 | using ScaffoldR.EntityFramework.Entities;
6 | using ScaffoldR.EntityFramework.Tests.Fakes;
7 | using ScaffoldR.EntityFramework.Tests.Helpers;
8 | using Xunit;
9 |
10 | namespace ScaffoldR.EntityFramework.Tests.Entities
11 | {
12 | public class EntityFrameworkRepositoryTests
13 | {
14 | [Fact]
15 | public void Query_CanGetReadOnlyEntity_WhichAreNotTrackedByContext()
16 | {
17 | using (var context = new FakeDbContext())
18 | {
19 | var repository = new EntityFrameworkRepository(() => context);
20 | var firstCustomer = repository.Query().First();
21 | var isFirstCustomerTrackedByContext = context.Entry(firstCustomer).State != EntityState.Detached;
22 |
23 | Assert.NotNull(firstCustomer);
24 | Assert.Equal(false, isFirstCustomerTrackedByContext);
25 | }
26 | }
27 |
28 | [Fact]
29 | public void Get_CanGetWritableEntity_WhenEntityExists()
30 | {
31 | using (var context = new FakeDbContext())
32 | {
33 | var repository = new EntityFrameworkRepository(() => context);
34 | var customer = repository.Get(1);
35 |
36 | Assert.NotNull(customer);
37 | Assert.Equal(EntityState.Unchanged, context.Entry(customer).State);
38 | }
39 | }
40 |
41 | [Fact]
42 | public void Save_CanCreateEntity_WhenEntityIsNotTrackedByContext()
43 | {
44 | using (var context = new FakeDbContext())
45 | {
46 | var repository = new EntityFrameworkRepository