C# some sort of plugin system - c#

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.

Related

Custom Attribute For Class Library Classes and Functions in C#

I'm developing 3rd party API connector bridge in class library NOT in ASP.NET.
User Levels
API has 3 user levels, lets say:
UserGoer
UserDoer
UserMaker
Service Restriction
Each API operation can work with one or multiple user level roles. For example, lets assume operations and reachable user levels as follows;
JokerService (reachable by UserGoer, UserMaker)
PokerService (reachable by UserGoer, UserDoer)
MokerService (reachable by UserGoer, UserDoer, UserMaker)
If UserDoer requests for JokerService, API returns bad request. JokerService is only reachable for UserGoer and UserMaker. So, I want to restrict and throw an exception.
User Token Structure
public interface IToken
{
string AccessToken { get; set; }
string RefreshToken { get; set; }
}
public class AuthenticationToken : IToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
public class UserGoerAuthenticationToken : AuthenticationToken
{
}
public class UserDoerAuthenticationToken : AuthenticationToken
{
}
public class UserMakerAuthenticationToken : AuthenticationToken
{
}
Enum
public enum TokenType
{
Undefined = 0,
UserGoer = 1,
UserDoer = 2,
UserMaker = 3
}
Customized Authentication Attribute
public class AuthenticationFilter : Attribute
{
public TokenType[] TokenTypes { get; private set; }
public AuthenticationFilter(params TokenType[] TokenTypes)
{
this.TokenTypes = TokenTypes;
}
}
Example Service
[AuthenticationFilter(TokenType.UserGoer, TokenType.UserMaker)]
internal class JokerService : BaseService<JokerEntity>
{
public JokerService(IToken AuthenticationToken) : base(AuthenticationToken)
{
var tokenTypes =
(typeof(JokerService).GetCustomAttributes(true)[0] as AuthenticationFilter)
.TokenTypes;
bool throwExceptionFlag = true;
foreach (var item in tokenTypes)
{
// Check AuthenticationToken is UserGoer or UserMaker by StartsWith function
if (AuthenticationToken.GetType().Name.StartsWith(item.ToString()))
{
throwExceptionFlag = false;
break;
}
}
if (throwExceptionFlag)
throw new Exception("Invalid Authentication Token");
}
public JokerEntity Create(RequestModel<JokerEntity> model) => base.Create(model);
public JokerEntity Update(RequestModel<JokerEntity> model) => base.Update(model);
public JokerEntity Get(RequestModel<JokerEntity> model) => base.Get(model);
public List<JokerEntity> List(RequestModel<JokerEntity> model) => base.List(model);
}
In summary, JokerService can be executable by UserGoer and UserMaker. UserDoer has no permission for this service.
As you see the the usage of AuthenticationFilter attribute, I'm getting custom attributes in the constructor, because i want to know what IToken is. If there is an irrelevant "User Authentication Token" type that is passed as parameter (IToken), program should be throw an exception.
This is my solution, do you think is there any best practice for my problem?
Thank you for your help.
Interesting question. My initial thought at constructive critique would be that the tokens accepted by a particular class via the attribute is something decided at compile time and is unable to change. But, the checking for permissions is happening on the construction of each object.
You can prevent this with a static constructor that sets the tokenTypes variable. Static constructors always run before instance constructors. This is also a good place to ensure that tokenTypes is never null (in the absence of your custom attribute).
Likewise, the looping through tokenTypes can probably be a function that takes in an IToken and the tokenTypes, and more importantly, could probably live in the BaseService.cs. Writing that logic once will make it easier to maintain when some future requirement necessitates its change. :)
See also: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
Hope this helps.

Too Many Dependency Inject

I currently have a class with around 40 dependency injection. It is a hard to maintain and unit test. I am not sure a good way around.
The code is done for any type of application process that is needed to process (New License, License Renewal, Student Registration, ...), there are around 80 different types applications and what sections are associated with each application type is determined by a database table.
I have a class with all of the possible properties, there are a several more than listed but you should get the idea. Each the properties have their own set of properties that are basic data types or object pointing to other classes.
class Application
{
[JsonProperty(PropertyName = "accounting")]
public Accounting Accounting { get; set; }
[JsonProperty(PropertyName = "application")]
public Application Application { get; set; }
[JsonProperty(PropertyName = "applicationType")]
public ApplicationType ApplicationType { get; set; }
[JsonProperty(PropertyName = "document")]
public List<Attachment> Document { get; set; }
[JsonProperty(PropertyName = "employment")]
public List<Employment> Employment { get; set; }
[JsonProperty(PropertyName = "enrollment")]
public Enrollment Enrollment { get; set; }
[JsonProperty(PropertyName = "individualAddressContact")]
public IndividualAddressContact IndividualAddressContact { get; set; }
[JsonProperty(PropertyName = "instructors")]
public List<Instructor> Instructors { get; set; }
[JsonProperty(PropertyName = "license")]
public License License { get; set; }
[JsonProperty(PropertyName = "licenseRenewal")]
public LicenseRenewal LicenseRenewal { get; set; }
[JsonProperty(PropertyName = "MilitaryService")]
public List<MilitaryService> MilitaryService { get; set; }
[JsonProperty(PropertyName = "paymentDetail")]
public PaymentDetail PaymentDetail { get; set; }
[JsonProperty(PropertyName = "photo")]
public List<Attachment> Photo { get; set; }
[JsonProperty(PropertyName = "portal")]
public Portal Portal { get; set; }
[JsonProperty(PropertyName = "section")]
public List<Section> Section { get; set; }
[JsonProperty(PropertyName = "testingCalendar")]
public TestingCalendar TestingCalendar { get; set; }
[JsonProperty(PropertyName = "testingScore")]
public List<TestingScore> TestingScore { get; set; }
[JsonProperty(PropertyName = "USCitizen")]
public USCitizen USCitizen { get; set; }
}
So this class is sent/received to an Angular 10 front end using Web API's.
When an application is requested the sections and the different properties are initiated and if the application has be started the progress will be reloaded. So it is possible some of properties will be pulled from the database and sent to the Angular app.
So I have something such as
Load(applicationTypeId, applicationId)
{
Get the sections for the application type
For each section in the sections
switch sectionid
case Documents
Load all of the documents required for the application type and get any documents uploaded
case Accounting
Load the payment details, if no payment made calculate the payment
case IndividualAddressContact
Load the person name/address/contact and set a few defaults if the person hasn't started.
.....
next
}
Save()
{
Save the application
switch current section
case Documents
Save all of the documents for the application
case Accounting
Save the payment details for the application
case IndividualAddressContact
Save the person name/address/contact for the application
.....
get the next section
Update the application current section
}
I have put all of the items in the switch into their own classes but in the end I still have 1 point for serialization/deserialization and still end up with to many dependencies injected. Creating a unit test with over 40 dependencies seems hard to maintain and given I won't know which properties will/won't used until an application is requested and loaded from database. I am unsure how to get around the switch, without at some point and time having to have all of the dependencies injected into 1 class.
I would appreciate some ideas of how to get around this.
"I currently have a class with around 40 dependency injection..." - Oh my gosh!
"It is a hard to maintain and unit test..." - I don't doubt that in the least!
SUGGESTED REFACTORING:
Create a class that manages "Applications" (e.g. "ApplicationManager").
Create an abstract class "Application".
One advantage of "abstract class" over "interface" here that you can put "common code" in the abstract base class.
Create a concrete subclass for each "Application" : public class NewLicense : Application, public class LicenseRenewal : Application, etc. etc.
... AND ...
Use DI primarily for those "services" that each concrete class needs.
I'll bet the constructors for your individual concrete classes will only need to inject three or four services ... instead of 40. Who knows - maybe your base class won't need any DI at all.
This is actually a design we're actually using in one of our production systems. It's simple; it's robust; it's flexible. It's working well for us :)
I would recommend using convention over configuration principle, with the Service Locator.
Declare something like IApplicationHandler interface in your program, e.g.
public interface IApplicationQueryHandler
{
Application Populate(Application application);
}
public interface IApplicationSaveHandler
{
Bool Save(Application application);
}
Then, write pieces of your code, with dependencies and such, e.g.
public class AccountingApplicationQueryHandler : IApplicationQueryHandler
{
public Application Populate(Application application) {
//// Load the payment details, if no payment made calculate the payment
return application;
}
}
public class AccountingApplicationSaveHandler : IApplicationSaveHandler
{
public Bool Save(Application application) {
//// Save the payment details for the application
return true; // this just flags for validation
}
}
// repeat for all other properties
Then in your controller, do something like
public class ApplicationController: Controller
{
public readonly IServiceProvider _serviceProvider;
public ApplicationController(IServiceProvider sp) {
_serviceProvider = sp;
}
public Application Load(string applicationTypeId, string applicationId)
{
var application = new Application(); // or get from db or whatever
var queryHandlers = _serviceProvider.GetServices(typeof(IApplicationQueryHandler));
foreach(var handler in queryHandlers) {
application = handler.Populate(application);
}
return application;
}
[HttpPost]
public bool Save(Application application)
{
var result = true;
var saveHandlers = _serviceProvider.GetServices(typeof(IApplicationSaveHandler));
foreach(var handler in queryHandlers) {
result = handler. Save(application);
}
return result;
}
}
You would need to register your handlers, which you can do e.g. like so:
var queryHandlers = Assembly.GetAssembly(typeof(IApplicationQueryHandler)).GetExportedTypes()
.Where(x => x.GetInterfaces().Any(y => y == typeof(IApplicationQueryHandler)));
foreach(queryHandler in queryHandlers) {
services.AddTransient(typeof(IApplicationQueryHandler), queryHandler);
}
// repeat the same for IApplicationSaveHandler
Now finally, you can write unit tests for part of the code like so
[TestClass]
public class AccountingApplicationQueryHandlerTests
{
[TestMethod]
public void TestPopulate()
{
// arrange
var application = new Application();
var handler = new AccountingApplicationQueryHandler(); // inject mocks here
// act
var result = handler.Populate(application);
// Assert
Assert.AreEqual(result. PaymentDetail, "whatever");
}
}
And you can test that your controller calls the right things by mocking IServiceProvider and injecting that with a couple of dummy handlers to confirm they are called correctly.
Following zaitsman's answer you also could create AggregatedApplicationQueryHandler and AggregatedApplicationSaveHandler and pass collection of concrete implementation of IApplicationQueryHandler and IApplicationSaveHandler to its constructor.
Then you don't need foreach loop inside controller(you loop over handlers inside aggregated handler) and always have only one handler passed to controller. Passing its by constructor parameter shouldn't be so much painful.
You also could create facade over some small services and aggregate theirs functions into one bigger facade service.

WEB API hangs after leaving ApiController method

My application has been built with ASP.NET MVC 4 and Web API. But I have a strange issue to share.
The corresponding code is below
public class MachinesController : ApiController
{
private GWData db = new GWData();
// GET api/Machines/5
public Machine GetMachine(int id)
{
Machine machine = db.Machines.Single(m => m.Id == id);
if (machine == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return machine;
}
Using following URL, I can examine my API Get method of a controller in Web API.
http://localhost/myweb/api/machines/1
And it worked but trying
http://localhost/myweb/api/machines/2
makes Web API hangs forever while memory usage of w3wp.exe keeps going up. So I had to eventually kill the w3wp.exe process. Further by making breakpoint inside of the GET method, I made sure that the hanging happens after getting right data and leaving the method.
How can I approach this kind of issue?
I should've found this cause earlier. This was a problem in serialization of Json. It took forever to serialize navigation properties of an entity if it has many related records. Of course, it was my fault to forget to disable lazy loading. Adding following code solved the problem.
public MachinesController()
{
db.ContextOptions.LazyLoadingEnabled = false;
}
I don't think your solution is correct. Instead you may want to have a model to view model structure, where view model object is flat and exposes only the properties you want to:
class Order
{
// properties you want to expose
public DateTime OrderDate { get; set; }
// navigation and other properties you don't want to expose
public Guid OrderId { get; set; }
public Customer Customer { get; set; }
public ICollection<Address> Addresses { get; set; }
public ICollection<Tax> Taxes { get; set; }
}
class OrderViewModel
{
public DateTime OrderDate { get; set; }
}
The easiest way to create one from another is to use AutoMapper.

API / Plugin Architecture Development Ideas

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

How do I design a specific super class

I am trying to refactor a solution to bring on board another project.
I have a Core project where common classes across projects reside.
I've tried to simpify my question by using 2 imaginary projects: Holidays and Weather...
I have a file load process setup for the Holidays project which has the following 2 classes:
public class Job
{
public virtual string CreatedBy { get; set; }
public virtual DateTime? CreatedDate { get; set; }
public virtual Security Security { get; set; }
protected IList<File> _files = new List<File>();
public virtual IEnumerable<File> Files
{
get { return _files; }
}
}
public class File
{
public virtual string FileName { get; set; }
public virtual FileType FileType { get; set; }
public virtual FileStatusType FileStatusType { get; set; }
public virtual Job Job { get; set; }
}
The file load process for the Weather project has exactly the same structure as Holidays, except that the Jobs class does not have a Security property.
My question is, is it possible to somehow move both classes into the Core project to allow both projects to use them?
Obviously Weather does not need the Security property, so I was thinking I would have a Core.Job class without Security, and then extend the Core.Job in Holidays.Job.
But once I do that, in the Core.File class, what Job is it referring to? As it sits in the Core project it must be the Core.Job.
So would I then need to have Job and File sit in Holidays, and Weather (and any other future projects) use the Core.Job and Core.File?
I don't want the Core project to have any references to sub projects.
I am using NHibernate, and so have mapping files - adding to the complexity.
Hope this is clear enough
Thanks
You can certainly do this, but I am not sure whether it brings you true benefit:
Does the Core itself work with the base Job in any way? If it does not, implementing Job separately in each project may help you keep coupling loose, even though I'd a little redundant. In code I wrote, I have sometimes introduced unnecessary dependencies by extracting interfaces without adding true benefit. This is why I am a bit precautious.
In case Core does acutal work with it, the part to refactor into the common base Job is perhaps the interface it works with.
You may think of an interface instead of a base class. Security may semantically belong to another interface. Moreover, you hand over a lot of control over your classes to the Core.
Do you ever hand a job from one project to another (or are they mapped to the same DB table via NHibernate?)? If you don't, an internal redundant class may be fine too.
Not very clear why confuse on the soluton offered by you (assuming that I right understood you)
//Core DLL
public class Job
{
public virtual string CreatedBy { get; set; }
public virtual DateTime? CreatedDate { get; set; }
protected IList<File> _files = new List<File>();
public virtual IEnumerable<File> Files
{
get { return _files; }
}
}
in the Hollidays you have
public class HollidayJob : Job
{
public virtual Security Security { get; set; }
}
in Weather simply use a type Job, if it selfsufficient.
In this case you refer CoreDLL from Holliday project and Weather. When you serialize it via NHibernate it for HollidayJob save one field more, but when Weather reads the same table it skips that field, as don't know anything, and don't actually care abotu it.
Hope this helps.

Categories