API / Plugin Architecture Development Ideas - c#

I'm trying to figure out a way to develop a plugin-based architecture software. The basic structure would be that my main application ('MainApp') will start, search through the plugin DLL files in a specified folder, and load them one by one using Activator. The DLL files are supposed to be created by my team and I plan on laying out a documentation for other users to develop the plugins as well.
Right now I have a sample project up and running. I use an interface class ('PluginInterface') through which I cast type and load plugins. I can communicate with the plugins through specified functions, properties and subroutines.
My question is that the interface method defines which properties, functions, subs or events can be found inside a plugin class. What I want to do is that I have many components or controls available in my MainApp. I need to allow my plugin to access those components. For example, I have a notification control ('NotifyCtrl') that would allow plugins to show popup notifications on the screen. That control has properties and methods of its own. So I have a big arsenal of controls that I want to allow plugin to access.
I cannot understand how to develop such architecture that runtime-loaded plugins are able to access controls/components of MainApp. I mean I can access components of plugin using PluginInterface, but how does the plugin know which components/properties/functions are available for use by MainApp. How should I write code inside one of my plugins (for example 'ChatPlugin')…. MainApp.NotifyCtrl.ShowNotification("hello")?
Thanks

What you need to do in such a case is create a base library off of which your application runs. This means that you need to create an abstract class or interface for every class you want the plugin developers to see.
For example, in your main app let's say you have a "User" class which you want to have shared events and variables:
//Create an instance of user in your application where you allow setting and getting the Name.
public class User : IUser
{
public string Name { get; set; }
public string Id { get; set; }
public event Action OnLogin = delegate { };
}
//Only allow the developers to get the name/id
public interface IUser
{
string Name { get; }
string Id { get; }
event Action OnLogin;
}
Then, for example if you want the developer to access all the logged in users in your application, you have some kind of main connecting point, such as a static class where you manage everything.
//Your functionality goes here
public class UserManager : IUserManager
{
private Dictionary<int, User> Users = new Dictionary<int, User>();
public override User this[int id]
{
get { return Users[id];}
}
public override IEnumerator<IUser> GetEnumerator()
{
return Users.Values.GetEnumerator();
}
public void Add(User user)
{
Users[user.Id] = user;
}
}
//What the user can see goes here
public abstract class IUserManager : IEnumerable<IUser>
{
public abstract User this[int id] { get; }
public abstract IEnumerator<IUser> GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
To tie it all up, and give them full access to access the enumerable:
public class MyApp : MyPluginApp
{
public static UserManager MyUserManager { get { return Manager as UserManager; } }
public static void Start()
{
//Start routine
Manager = new UserManager();
MyUserManager.Add(new User {Id = 0, Name = "test"});
}
}
public class MyPluginApp
{
public static IUserManager Manager { get; protected set; }
}
Then, your plugin developer can do as something as easy as:
var userOfInterest = MyPluginApp.Manager.First(x => x.Name == "test"); //Get user by the name of test
They can easily access Id / name, but they cant set it, nor can they add new users, etc. This also makes it easier for you because you do not need to create extra functions for every function you want to export, instead you just create a function in the base class, and implement it in your application.

I think I've found the solution to what I'm looking for. Using the Reflection method of loading plugins are runtime is usually a one-way interaction method... host application using the capabilities of plugin class. What I'm looking for is the both ways, host using plugin's resources and the plugin using host's controls/resources, etc.
So the Reflection method is outdated. The 3.5 and above .NET frameworks provide System.AddIn feature, this is made for such type of architectures.
See http://msdn.microsoft.com/en-us/magazine/cc163476.aspx

Related

Improve design with IOC/DI

I'm currently trying to find a better design for my multi-module solution using DI/IOC, but now I'm somehow lost. I have a solution where different kind of entities can be distributed to recipients via different channels.
This is a simplified version of my classes:
#region FTP Module
public interface IFtpService
{
void Upload(FtpAccount account, byte[] data);
}
public class FtpService : IFtpService
{
public void Upload(FtpAccount account, byte[] data)
{
}
}
#endregion
#region Email Module
public interface IEmailService :IDistributionService
{
void Send(IEnumerable<string> recipients, byte[] data);
}
public class EmailService : IEmailService
{
public void Send(IEnumerable<string> recipients, byte[] data)
{
}
}
#endregion
public interface IDistributionService { }
#region GenericDistributionModule
public interface IDistributionChannel
{
void Distribute();
}
public interface IDistribution
{
byte[] Data { get; }
IDistributionChannel DistributionChannel { get; }
void Distribute();
}
#endregion
#region EmailDistributionModule
public class EmailDistributionChannel : IDistributionChannel
{
public void Distribute()
{
// Set some properties
// Call EmailService???
}
public List<string> Recipients { get; set; }
}
#endregion
#region FtpDistributionModule
public class FtpDistributionChannel : IDistributionChannel
{
public void Distribute()
{
// Set some properties
// Call FtpService???
}
public FtpAccount ftpAccount { get; set; }
}
#endregion
#region Program
public class Report
{
public List<ReportDistribution> DistributionList { get; private set; }
public byte[] reportData{get; set; }
}
public class ReportDistribution : IDistribution
{
public Report Report { get; set; }
public byte[] Data { get { return Report.reportData; } }
public IDistributionChannel DistributionChannel { get; private set; }
public void Distribute()
{
DistributionChannel.Distribute();
}
}
class Program
{
static void Main(string[] args)
{
EmailService emailService = new EmailService();
FtpService ftpService = new FtpService();
FtpAccount aAccount;
Report report;
ReportDistribution[] distributions =
{
new ReportDistribution(new EmailDistributionChannel(new List<string>("test#abc.xyz", "foo#bar.xyz"))),
new ReportDistribution(new FtpDistributionChannel(aAccount))
};
report.DistributionList.AddRange(distributions);
foreach (var distribution in distributions)
{
// Old code:
// if (distribution.DistributionChannel is EmailDistributionChannel)
// {
// emailService.Send(...);
// }else if (distribution.DistributionChannel is FtpDistributionChannel)
// {
// ftpService.Upload(...);
// }else{ throw new NotImplementedException();}
// New code:
distribution.Distribute();
}
}
}
#endregion
In my current solution it is possible to create and store persistent IDistribution POCOs (I'am using a ReportDistribution here) and attach them to the distributable entity (a Report in this example).
E.g. someone wants to distribute an existing Report via Email to a set of recipients. Therefore he creates a new ReportDistribution' with anEmailDistributionChannel'. Later he decides to distribute the same Report via FTP to a specified FtpServer. Therefore he creates another ReportDistribution with an FtpDistributionChannel.
It is possible to distribute the same Report multiple times on the same or different channels.
An Azure Webjob picks up stored IDistribution instances and distributes them. The current, ugly implementation uses if-else to distribute Distributions with a FtpDistributionChannel via a (low-level) FtpService and EmailDistributionChannels with an EmailService.
I'm now trying to implement the interface method Distribute() on FtpDistributionChannel and EmailDistributionChannel. But for this to work the entities need a reference to the services. Injecting the Services into the entities via ConstructorInjection seems to be considered bad style.
Mike Hadlow comes up with three other solutions:
Creating Domain Services. I could e.g. create a FtpDistributionService, inject a FtpService and write a Distribute(FtpDistributionChannel distribution) method (and also a EmailDistributionService). Apart from the drawback mentioned by Mike, how can I select a matching DistributionService based on the IDistribution instance? Replacing my old if-else with another one does not feel right
Inject IFtpService/EMailService into the Distribute() method. But how should I define the Distribute() method in the IDistribution interface? EmailDistributionChannel needs an IEmailService while FtpDistributionChannel need an IFtpService.
Domain events pattern. I'm not sure how this can solve my problem.
Let me try to explain why I came up with this quite complicated solution:
It started with a simple list of Reports. Soon someone asked me to send reports to some recipients (and store the list of recipients). Easy!
Later, someone else added the requirement to send a report to a FtpAccount. Different FtpAccounts are managed in the application, therefore the selected account should also be stored.
This was to the point where I added the IDistributionChannel abstraction. Everything was still fine.
Then someone needed the possibility to also send some kind of persistent Logfiles via Email. This lead to my solution with IDistribution/IDistributionChannel.
If now someone needs to distribute some other kind of data, I can just implement another IDistribution for this data. If another DistributionChannel (e.g. Fax) is required, I implement it and it is available for all distributable entities.
I would really appreciate any help/ideas.
First of all, why do yo create interfaces for the FtpAccount? The class is isolated and provide no behavior that need to be abstracted away.
Let's start with your original problem and build from there. The problem as I interpret it as that you want to send something to a client using a different set of mediums.
By expressing it in code it can be done like this instead:
public void SendFileToUser(string userName, byte[] file)
{
var distributions = new []{new EmailDistribution(), new FtpDistribution() };
foreach (var distribution in distributions)
{
distribution.Distribute(userName, file);
}
}
See what I did? I added a bit of context. Because your original use case was way to generic. It's not often that you want to distribute some arbitrary data to an arbitrary distribution service.
The change that I made introduces a domain and a real problem.
With that change we can also model the rest of the classes a bit different.
public class FtpDistributor : IDistributor
{
private FtpAccountRepository _repository = new FtpAccountRepository();
private FtpClient _client = new FtpClient();
public void Distribute(string userName, byte[] file)
{
var ftpAccount = _repository.GetAccount(userName);
_client.Connect(ftpAccount.Host);
_client.Authenticate(ftpAccount.userName, ftpAccount.Password);
_Client.Send(file);
}
}
See what I did? I moved the responsibility of keeping track of the FTP account to the actual service. In reality you probably have an administration web or similar where the account can be mapped to a specific user.
By doing so I also isolated all handling regarding FTP to within the service and therefore reduced the complexity in the calling code.
The email distributor would work in the same way.
When you start to code problems like this, try to go from top->down. It's otherwise easy to create an architecture that seems to be SOLID while it doesn't really solve the actual business problem.
Update
I've read your update and I don't see why you must use the same classes for the new requirements?
Then someone needed the possibility to also send some kind of persistent Logfiles via Email
That's an entirely different use case and should be separated from the original use case. Create new code for it. The SmtpClient in .NET is quite easy to us and do not need to be abstracted away.
If now someone needs to distribute some other kind of data, I can just implement another IDistribution for this data.
Why? what complexity are you trying to hide?
If another DistributionChannel (e.g. Fax) is required, I implement it and it is available for all distributable entities
No. Distributing thing A is not the same as distributing thing B. You can't for instance transport parts of a large bridge on an airpane, either a freight ship or a truck is required.
What I'm trying to say is that creating too generic abstractions/contracts to promote code reuse seems like a good idea, but it usually just make your application more complex or less readable.
Create abstractions when there is real complexity issues and not on before hand.

Successfully implementing custom UserManager<IUser> in Identity 2.0

I'm trying to navigate the black hole that is the custom implementation of Identity Membership. My goal right now is simply to get this line from my ApiController to correctly retrieve my UserManager:
public IHttpActionResult Index()
{
var manager = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<MyUser,int>>();
//manager is null
}
Here's my setup. In my Startup's Configuration I set up the WebApi and add my OwinContext:
app.CreatePerOwinContext<UserManager<MyUser,int>>(Create);
My Create method:
public static UserManager<User,int> Create(IdentityFactoryOptions<UserManager<MyUser,int>> options, IOwinContext context)
{
return new UserManager<MyUser,int>(new UserStore(new DbContext()));
}
the rest is the most basic implementation I can make.
MyUser:
public class MyUser : IUser<int>
{
public int Id { get; set; }
public string UserName { get; set; }
}
MyUserStore:
public class MyUserStore : IUserStore<MyUser,int>
{
private IdentityDbContext context;
public MyUserStore(IdentityDbContext c)
{
context = c;
}
//Create,Delete, etc implementations
}
MyDbContext:
public class MyDbContext : IdentityDbContext
{
public MyDbContext() : base("Conn")
{
}
}
This is all for the sake of learning how Identity works, which I'm pretty convinced no one actually knows. I want to be able to fully customize my Users and Roles eventually, avoiding Microsoft's IdentityUser.
Again, my issue right now is that in my controller, I am getting null when trying to retrieve my UserManager.
Any and all help is greatly appreciated.
I had several errors, but the main one was that my Startup class looked like :
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseWebApi(new WebApiConfig());
app.CreatePerOwinContext(MyDbContext.Create);
app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
}
}
Of course, the OWIN pipeline will plug my dependencies after firing off the WebAPI calls. Switching those around was my main problem.
In addition, I finally found this great guide way down in my Google search. It answers pretty much everything I was getting at. I needed to implement a concrete class that was a UserManager<MyUser,int>
I hope this is able to help someone later on.
Are you using MyIdentity.User or MyIdentity.MyUser? You have two different objects passed into the TUser parameter in your examples.
I tested your implementation and did not have issues retrieving the registered instance of the UserManager.
To fully customize your Users and Roles, you will need to end up writing a new implementation of the UserManager in order to get your Authentication, Claims, Roles, method calls, etc to work.
If you are trying to learn how Identity works, I would suggest working with the default implementation of UserManager and IdentityUser. Get that to work first.
Here is a good tutorial
Eventually, create your own users implementing IdentityUser. All of the UserManager functions will work and you will have access to your new properties. The additional properties will automatically be built into the AspnetUser table generated by the IdentityDbContext.
public MyIdentityUser : IdentityUser
{
public int Id {get; set;}
public string CustomUserId {get; set;}
public string UserId { get; set; }
}
Or you can start building your custom MyIdentityUser with foreign key references to other objects.
public MyIdentityUser : IdentityUser
{
public virtual UserProperties Properties { get; set; }
}
Does this help any?

Property type of two classes

I'm writing session manager class in .NET MVC 4 and I got stuck at the point of creating SqlConfiguration.
Here is one of the properties from the class:
public static MsSqlConfiguration SqlConfig { get; set; }
All working perfectly excluding the fact that I can manage sessions only from MS SQLServer.
I want to do something like this:
public static MsSqlConfiguration,SQLiteConfiguration SqlConfig { get; set; }
And I know it isn't possible so I don't know what to do.
Thanks.
You can create a class with these 2 properties and Use them. I know its very basic
class MyConfig
{
public static MsSqlConfiguration SqlConfig { get; set; }
public static SQLiteConfiguration SQLiteConfig { get; set; }
}
Use them like
public static MyConfig SqlConfig { get; set; }
What about a dictionary?
public static IReadOnlyDictionary<string, IPersistenceConfigurer> DbConfigurations =
new ReadOnlyDictionary<string, IPersistenceConfigurer>(
new Dictionary<string, IPersistenceConfigurer>
{
{ "azure", MsSqlConfiguration.MsSql2008
.ConnectionString("ConnectionString")
.Dialect<MsSqlAzure2008Dialect>()
.Driver<SqlAzureClientDriver>() },
{ "mssql", MsSqlConfiguration.MsSql2008
.ConnectionString("ConnectionString")
.Dialect<MsSql2008Dialect>() },
{ "sqlite", SQLiteConfiguration.Standard
.InMemory() },
// etc..
});
IPersistenceConfigurer is an interface that any database configuration must implement.
As it's a dictionary, you can always check if a database configuration is present by calling DbConfigurations.ContainsKey("mssql").
Another option is using a generic list of IPersistenceConfigurer (aka List<IPersistenceConfigurer>) and get a configuration using LINQ OfType<T> extension method as follows:
dbConfigs.OfType<MsSqlConfiguration >().Single()
...or
dbConfigs.Single(config => config is MsSqlConfiguration)
Another option, if you're using Dependency Injection and an IoC container such as Castle Windsor is to register a factory with the container that can provide an instance of IPersistenceConfigurer to any components that require it. This way you can register different components for the IPersistenceConfigurer service depending on which environment you are running in (as I assume that you only need one particular IPersistenceConfigurer for the application at any one time).

Where to put global rules validation in DDD

I'm new to DDD, and I'm trying to apply it in real life. There is no questions about such validation logic, as null check, empty strings check, etc - that goes directly to entity constructor/property. But where to put validation of some global rules like 'Unique user name'?
So, we have entity User
public class User : IAggregateRoot
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
// other data and behavior
}
And repository for users
public interface IUserRepository : IRepository<User>
{
User FindByName(string name);
}
Options are:
Inject repository to entity
Inject repository to factory
Create operation on domain service
???
And each option more detailed:
1 .Inject repository to entity
I can query repository in entities constructor/property. But I think that keeping reference to repository in entity is a bad smell.
public User(IUserRepository repository)
{
_repository = repository;
}
public string Name
{
get { return _name; }
set
{
if (_repository.FindByName(value) != null)
throw new UserAlreadyExistsException();
_name = value;
}
}
Update: We can use DI to hide dependency between User and IUserRepository via Specification object.
2. Inject repository to factory
I can put this verification logic in UserFactory. But what if we want to change name of already existing user?
3. Create operation on domain service
I can create domain service for creating and editing users. But someone can directly edit name of user without calling that service...
public class AdministrationService
{
private IUserRepository _userRepository;
public AdministrationService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void RenameUser(string oldName, string newName)
{
if (_userRepository.FindByName(newName) != null)
throw new UserAlreadyExistException();
User user = _userRepository.FindByName(oldName);
user.Name = newName;
_userRepository.Save(user);
}
}
4. ???
Where do you put global validation logic for entities?
Thanks!
Most of the times it is best to place these kind of rules in Specification objects.
You can place these Specifications in your domain packages, so anybody using your domain package has access to them. Using a specification, you can bundle your business rules with your entities, without creating difficult-to-read entities with undesired dependencies on services and repositories. If needed, you can inject dependencies on services or repositories into a specification.
Depending on the context, you can build different validators using the specification objects.
Main concern of entities should be keeping track of business state - that's enough of a responsibility and they shouldn't be concerned with validation.
Example
public class User
{
public string Id { get; set; }
public string Name { get; set; }
}
Two specifications:
public class IdNotEmptySpecification : ISpecification<User>
{
public bool IsSatisfiedBy(User subject)
{
return !string.IsNullOrEmpty(subject.Id);
}
}
public class NameNotTakenSpecification : ISpecification<User>
{
// omitted code to set service; better use DI
private Service.IUserNameService UserNameService { get; set; }
public bool IsSatisfiedBy(User subject)
{
return UserNameService.NameIsAvailable(subject.Name);
}
}
And a validator:
public class UserPersistenceValidator : IValidator<User>
{
private readonly IList<ISpecification<User>> Rules =
new List<ISpecification<User>>
{
new IdNotEmptySpecification(),
new NameNotEmptySpecification(),
new NameNotTakenSpecification()
// and more ... better use DI to fill this list
};
public bool IsValid(User entity)
{
return BrokenRules(entity).Count() == 0;
}
public IEnumerable<string> BrokenRules(User entity)
{
return Rules.Where(rule => !rule.IsSatisfiedBy(entity))
.Select(rule => GetMessageForBrokenRule(rule));
}
// ...
}
For completeness, the interfaces:
public interface IValidator<T>
{
bool IsValid(T entity);
IEnumerable<string> BrokenRules(T entity);
}
public interface ISpecification<T>
{
bool IsSatisfiedBy(T subject);
}
Notes
I think Vijay Patel's earlier answer is in the right direction, but I feel it's a bit off. He suggests that the user entity depends on the specification, where I belief that this should be the other way around. This way, you can let the specification depend on services, repositories and context in general, without making your entity depend on them through a specification dependency.
References
A related question with a good answer with example: Validation in a Domain Driven Design.
Eric Evans describes the use of the specification pattern for validation, selection and object construction in chapter 9, pp 145.
This article on the specification pattern with an application in .Net might be of interest to you.
I would not recommend disallowing to change properties in entity, if it's a user input.
For example, if validation did not pass, you can still use the instance to display it in user interface with validation results, allowing user to correct the error.
Jimmy Nilsson in his "Applying Domain-Driven Design and Patterns" recommends to validate for a particular operation, not just for persisting. While an entity could be successfully persisted, the real validation occurs when an entity is about to change it's state, for example 'Ordered' state changes to 'Purchased'.
While creating, the instance must be valid-for-saving, which involves checking for uniqueness. It's different from valid-for-ordering, where not only uniqueness must be checked, but also, for example, creditability of a client, and availability at the store.
So, validation logic should not be invoked on a property assignments, it should be invoked upon aggregate level operations, whether they are persistent or not.
Edit: Judging from the other answers, the correct name for such a 'domain service' is specification. I've updated my answer to reflect this, including a more detailed code sample.
I'd go with option 3; create a domain service specification which encapsulates the actual logic that performs the validation. For example, the specification initially calls a repository, but you could replace it with a web service call at a later stage. Having all that logic behind an abstract specification will keep the overall design more flexible.
To prevent someone from editing the name without validating it, make the specification a required aspect of editing the name. You can achieve this by changing the API of your entity to something like this:
public class User
{
public string Name { get; private set; }
public void SetName(string name, ISpecification<User, string> specification)
{
// Insert basic null validation here.
if (!specification.IsSatisfiedBy(this, name))
{
// Throw some validation exception.
}
this.Name = name;
}
}
public interface ISpecification<TType, TValue>
{
bool IsSatisfiedBy(TType obj, TValue value);
}
public class UniqueUserNameSpecification : ISpecification<User, string>
{
private IUserRepository repository;
public UniqueUserNameSpecification(IUserRepository repository)
{
this.repository = repository;
}
public bool IsSatisfiedBy(User obj, string value)
{
if (value == obj.Name)
{
return true;
}
// Use this.repository for further validation of the name.
}
}
Your calling code would look something like this:
var userRepository = IoC.Resolve<IUserRepository>();
var specification = new UniqueUserNameSpecification(userRepository);
user.SetName("John", specification);
And of course, you can mock ISpecification in your unit tests for easier testing.
I’m not an expert on DDD but I have asked myself the same questions and this is what I came up with:
Validation logic should normally go into the constructor/factory and setters. This way you guarantee that you always have valid domain objects. But if the validation involves database queries that impact your performance, an efficient implementation requires a different design.
(1) Injecting Entities: Injecting entities can be technical difficult and also makes managing application performance very hard due to the fragmentation of you database logic. Seemingly simple operations can now have an unexpectedly performance impact. It also makes it impossible to optimize your domain object for operations on groups of the same kind of entities, you no longer can write a single group query, and instead you always have individual queries for each entity.
(2) Injecting repository: You should not put any business logic in repositories. Keep repositories simple and focused. They should act as if they were collections and only contain logic for adding, removing and finding objects (some even spinoff the find methods to other objects).
(3) Domain service This seems the most logical place to handle the validation that requires database querying. A good implementation would make the constructor/factory and setters involved package private, so that the entities can only be created / modified with the domain service.
I would use a Specification to encapsulate the rule. You can then call when the UserName property is updated (or from anywhere else that might need it):
public class UniqueUserNameSpecification : ISpecification
{
public bool IsSatisifiedBy(User user)
{
// Check if the username is unique here
}
}
public class User
{
string _Name;
UniqueUserNameSpecification _UniqueUserNameSpecification; // You decide how this is injected
public string Name
{
get { return _Name; }
set
{
if (_UniqueUserNameSpecification.IsSatisifiedBy(this))
{
_Name = value;
}
else
{
// Execute your custom warning here
}
}
}
}
It won't matter if another developer tries to modify User.Name directly, because the rule will always execute.
Find out more here
In my CQRS Framework, every Command Handler class also contains a ValidateCommand method, which then calls the appropriate business/validation logic in the Domain (mostly implemented as Entity methods or Entity static methods).
So the caller would do like so:
if (cmdService.ValidateCommand(myCommand) == ValidationResult.OK)
{
// Now we can assume there will be no business reason to reject
// the command
cmdService.ExecuteCommand(myCommand); // Async
}
Every specialized Command Handler contains the wrapper logic, for instance:
public ValidationResult ValidateCommand(MakeCustomerGold command)
{
var result = new ValidationResult();
if (Customer.CanMakeGold(command.CustomerId))
{
// "OK" logic here
} else {
// "Not OK" logic here
}
}
The ExecuteCommand method of the command handler will then call the ValidateCommand() again, so even if the client didn't bother, nothing will happen in the Domain that is not supposed to.
in short you have 4 options:
IsValid method: transition an entity to a state (potentially invalid) and ask it to validate itself.
Validation in application services.
TryExecute pattern.
Execute / CanExecute pattern.
read more here
Create a method, for example, called IsUserNameValid() and make that accessible from everywhere. I would put it in the user service myself. Doing this will not limit you when future changes arise. It keeps the validation code in one place (implementation), and other code that depends on it will not have to change if the validation changes You may find that you need to call this from multiple places later on, such as the ui for visual indication without having to resort to exception handling. The service layer for correct operations, and the repository (cache, db, etc.) layer to ensure that stored items are valid.
I like option 3. Simplest implementation could look so:
public interface IUser
{
string Name { get; }
bool IsNew { get; }
}
public class User : IUser
{
public string Name { get; private set; }
public bool IsNew { get; private set; }
}
public class UserService : IUserService
{
public void ValidateUser(IUser user)
{
var repository = RepositoryFactory.GetUserRepository(); // use IoC if needed
if (user.IsNew && repository.UserExists(user.Name))
throw new ValidationException("Username already exists");
}
}
Create domain service
Or I can create domain service for
creating and editing users. But
someone can directly edit name of user
without calling that service...
If you properly designed your entities this should not be an issue.

C# some sort of plugin system

I am a mobile web developer and trying to monetize my traffic with mobile ad services and i have a problem.
First of all to get most of out of your ads you usually need to do server side request to advert company's servers and there are quite few ad services. Problem starts when you want to use them in one site.
All have different approaches to server side calls and trying to maintain and implement those ad codes becomes pain after a while.
So I decided to write a class system where i can simply create methods for every company and upload it to my site.
So far i have
public Advert class
public AdPublisher class with GetAd method that returns an Advert
public Adservice class that has Service names as enum
I also have converted server request codes of all ad services i use to classes.
It works ok but I want to be able to create an ad service class upload it so that asp.net app can import/recognize it automatically like a plugin system.
As I am new to .net I have no idea where to start or how to do it.
To make thing clear here are my classes
namespace Mobile.Publisher
{
public class AdPublisher
{
public AdPublisher()
{
IsTest = false;
}
public bool IsTest { get; set; }
public HttpRequest CurrentVisitorRequestInfo { get; set; }
public Advert GetAd(AdService service)
{
Advert returnAd = new Advert();
returnAd.Success = true;
if (this.CurrentVisitorRequestInfo == null)
{
throw new Exception("CurrentVisitorRequestInfo for AdPublisher not set!");
}
if (service == null)
{
throw new Exception("AdService not set!");
}
if (service.ServiceName == AdServices.Admob)
{
returnAd.ReturnedAd = AdmobAds("000000");
}
return returnAd;
}
}
public enum AdServices
{
Admob,
ServiceB,
ServiceC
}
public class Advert
{
public bool Success { get; set; }
public string ReturnedAd { get; set; }
}
public partial class AdService
{
public AdServices ServiceName { get; set; }
public string PublisherOrSiteId { get; set; }
public string ZoneOrChannelId { get; set; }
}
private string AdmobAds(string publisherid)
{
//snip
return "test"
}
}
Basically i want to be able to add another ad service and code like
private string AdmobAds(string publisherid){
}
So that it can be imported and recognised as ad service.
I hope i was clear enough
Ths seems like a pretty vague/general question, and considering you mentioned you're no too familiar with .NET, I thought I'd point you in the direction of the Managed Extensibility Framework. This is an official Micrsoft library designed for creating plugin/add-in systems (it's like a specialised Inversion of Control framework). Note that in .NET 4.0, it's actually part of the framework base class library. There's also a great MSDN page on Add-ins and Extensibility - relating to the System.AddIn namespace - which you may find pretty helpful too.
You can load assemblies dynamically, then query the list of classes and check whether the class is derived from your interface. Check the "Assembly" class.

Categories