I have on my hands a Windows forms application where there is a clear separation of GUI and business logic. The solution is big (40 projects, thousands of classes, about 2000 database tables). My task is to find a solution on how to reuse business logic to build a web application as a front end.
The main issue is, I think, our static Session class which is used by every other class in the solution:
public static class Session
{
public static string CurrentUser { get; set; }
public static string CurrentDatabase { get; set; }
public static string CurrentCompanyProfile { get; set; }
public static string CurrentLanguage { get; set; }
}
This class will not work in ASP.NET where it will be shared by all users and I cannot replace it since it is used a lot.
I was thinking that I need to remove all information from this class and keep just the interface. By calling the get method of an property code would somehow redirect this call to HttpContext.Current.Session where I would store a class which would contain all this info.
I'm not sure how to do this properly considering that Session resides in an assembly which will not have a reference to System.Web and considering that I must not disrupt our WinForms implementation.
Thanks.
Assuming you can update the Session class, you can abstract the storage of the properties in the Session class. In your current application you can create a simple in-memory storage, and in the web application you can create a web-session storage.
First define a session-value-provider, which you use in your current static Session class.
public interface ISessionValueProvider {
string CurrentUser { get; set; }
string CurrentDatabase { get; set; }
string CurrentCompanyProfile { get; set; }
string CurrentLanguage { get; set; }
}
public static class Session {
private static ISessionValueProvider _sessionValueProvider;
public static void SetSessionValueProvider(ISessionValueProvider provider) {
_sessionValueProvider = provider;
}
public static string CurrentUser {
get { return _sessionValueProvider.CurrentUser; }
set { _sessionValueProvider.CurrentUser = value; }
}
// Etc for the other props
}
Than for your current application, define a sesion value provider which uses memory to storage the values.
public class MemorySessionValueProvider: ISessionValueProvider {
public string CurrentUser {get; set; }
// Etc for the other props
}
To use it, create an instance and give it to the static session class. For instance, you can add this to your Main method.
Session.SetSessionValueProvider(new MemorySessionValueProvider());
Now for your web application, create a session value provider which uses the web-session.
public class WebSessionValueProvider: ISessionValueProvider {
private const string CURRENTUSERKEY = "CurrentUser"; // TODO: Change this if necessary
public string CurrentUser {
get { return (string)HttpContext.Current.Session[CURRENTUSERKEY]; }
set { HttpContext.Current.Session[CURRENTUSERKEY] = value; }
}
// Etc for the other props
}
And again, give an instance of this web-session-value-provider to the static session class. For instance, in the global.asax.
Session.SetSessionValueProvider(new WebSessionValueProvider);
I'd use IoC container (for example Castle Windsor) for this. Declare an interface, for example, IStateManager:
public interface IStateManager
{
T GetItem<T>(string key);
SetItem<T>(string key, T value);
}
Then, your implementation of the Session class will change like the following:
public static class Session
{
private static IStateManager _manager;
private static IStateManager Manager
{
get
{
if (_manager == null)
{
IStateManager m = null; // Get instance using IoC container
Interlocked.CompareExchange(ref _manager, m, null);
}
return _manager;
}
}
public static string CurrentUser
{
get { return Manager.GetItem<string>("CurrentUser"); }
set { Manager.SetItem<string>("CurrentUser", value); }
}
// The rest is similar
}
For WinForms, the implementation will just operate on a static instance, for ASP.NET you'd have a different implementation that maintains data in the session. The benefit is that you'll just have different installers for different environments and your code doesn't need to know about them at all (therefore, the logic won't be dependent on either WinForms or ASP.NET).
Also, this approach is testable (it's very easy to mock the IStateManager using Moq, for example).
Related
I'm having trouble with getting my static main method to play nicely with my backend code.
Here's the backend stuff:
public interface ITicketGenerationService
{
string CreateTicket(DateTime begin, DateTime end);
}
public class TicketGenerationService : ITicketGenerationService
{
public static IRepository<Ticket> Repository { get; set; }
public TicketGenerationService(IRepository<Ticket> repository)
{
Repository = repository;
}
public string CreateTicket(DateTime begin, DateTime end)
{
//do stuff with Repository
//return status string to Main method
}
}
Here's where my console application begins:
public class TicketMain
{
public ITicketGenerationService TicketGenerationService { get; set; }
static void Main(string[] args)
{
var priorityOneTickets = TicketGenerationService.CreateTicket(begin, end);
}
}
So I initially get this error:
An object reference is required for the non-static field, method, or
property 'TicketMain.TicketGenerationService'
If I change CreateTicket to static, I get another error:
TicketGenerationService does not implment interface member
ITicketGenerationService.CreateTicket(DateTime, DateTime).
ITicketGenerationService.CreateTicket(DateTime, DateTime) cannot
implement an interface member because it is static.
If I try to add this:
var ticketingService = new TicketGenerationService();
to the main method, I'm afraid that will mess with my dependency injection(autofac).
I understand the errors, but I can't make everything static, and I'm afraid if I start instantiating, I'll lose all my data I gain via dependency injection.
Is there anyway around this?
Thanks!
It's not the TicketGenerationService.CreateTicket method that the error is referring to, it's your TicketGenerationService property in the TicketMain class.
You just need to change your property to static:
public static ITicketGenerationService TicketGenerationService { get; set; }
I was asked to use a table to store status of an entity type. Normally I used always enums for that before.
There is a business logic in which the status of the entity changing. This logic is encapsulated in the entity. It was easy when the status was an enum type. But now I would need to inject a service to get the required status. I do not know if it is a good idea to inject a service (like StatusService) into that method making the method depend on IStatusService.
Example code:
public class MyEntity
{
public MyEntityStatus Status { set; get; }
public void MethodInWhichStatusMayChange(IMyEntityStatusService myEntityStatusService)
{
//using myEntityStatusService to get the status when it should change
}
}
public class MyEntityStatus
{
public string Name { set; get; }
}
public interface IMyEntityStatusService
{
MyEntityStatus GetStatusA();
MyEntityStatus GetStatusB();
MyEntityStatus GetStatusC();
}
It is better to inject the service in the class constructor:
public class MyEntity
{
private readonly IMyEntityStatusService myEntityStatusService;
public MyEntity(IMyEntityStatusService myEntityStatusService)
{
this.myEntityStatusService = myEntityStatusService;
}
public MyEntityStatus Status { set; get; }
public void MethodInWhichStatusMayChange()
{
//now you use the private myEntityStatusService field
}
}
This will make your life easier if you decide to use a dependency injection engine, and also your code will be cleaner, easier to use (you don't have to be passing around instances of IMyEntityStatusService), and as pointed out in the comments, easier to test.
I have a class which initializes its properties in its constructor.
public class Criteria
{
public bool Chapter1 { get; set; }
public bool Chapter2 { get; set; }
...
public uint MaxResults { get; set; }
public int Hits { get; set; }
public Criteria()
{
Chapter1 = false;
Chapter2 = false;
...
MaxResults = 100;
Hits = -1;
}
}
This class is used internally within a web-service to configure searches on a DB. When I construct the class internally, the correct initialization is performed and operation is as anticipated.
However, the class is also exposed as a parameter in a Method to this Web-Service :
[WebMethod]
public List<xxx> GetxxxCollection(string requestingUserName, Criteria sc)
{
...
}
Prior to the clients call to this web-service, the Criteria object is constructed and configured. But, because its exposed through the web-service, the constructor is not actually called and the client does not always set all required values correctly.
Given that we have limited control over the client code, Whats the best strategy to ensure that appropriate initial values are set ?
You cannot control the client in any way. The "Service" class on the client is in no way related to the service class that contains the constructor. It's just a "proxy" class, not the real thing.
Maybe you can use the nullable fields, so that you know client hasn't set any value in the fields.
Don't use auto-implemented properties in your class, but instead use the old manual properties with backing-fields which might be initialized by default without a constructor invocation:
public class Criteria
{
private int _maxResults = 100;
//-----------------------------------------------------------------------
public int MaxResults
{
get{ return _maxResult; }
set{ _maxResults = value; }
}
}
I found out about properties a couple of days ago(not sure if I understood how to use them very well). So I decided to make some tests.
so here's what Ive done :
I created a class that contains some properties such as :
public string _string1 { get; set; }
public string _string2 { get; set; }
and then I created a method in the same class lets say like this :
public static string Example()
{
switch(_string1.length > _string2.length)
{
case true :
return _string1;
break;
default : return _string2;
}
}
just a stupid example to understand a bit
and then I called the method from the main class after that I got a couple of errors :
An object reference is required for the non-static field, method, or property 'xxx.properties._string1.get'
Well its certainly a stupid mistake but I'm new to c# and I could use some assistance.
You need to make your properties static too:
public static string _string1 { get; set; }
public static string _string2 { get; set; }
Essentially a static method has no state. Those fields when declared in a non-static manner are essentially like a state, therefore it can't access them. By marking them static you say this is the Global value for the AppDomain.
One thing to be wary of using static fields like this however is if you start using any sort of threading and try to store state then you can end up with nasty issues to debug because you've no idea what state you're shared resources are in.
A way to protect against this (if you don't need state) is to define these as constants fields instead. Then you can't modify them, but means you need not worry about someone changing them when you didn't expect it.
public const string _string1;
public const string _string2;
A static method can always access other static members only. Now since your properties are not static hence your static method cannot access/manipulate them.
You can make these fields as static and then the error will go away. Once these are static no object reference would be required to access them.
They can then be simply accessed through the classname itself.
for example
public class YourClass
{
public static string _string1 { get; set; }
public static string _string2 { get; set; }
public static string Example()
{
switch(_string1.length > _string2.length)
{
case true :
return _string1;
break;
default : return _string2;
}
}
}
Now in your program:
YourClass._string1="some string"; // You can access the static properties with class name
YourClass._string2="some other string";
YourClass.Example() // You can call the static function with class name.
It's all about instance versus static scope. Whilst the examples above make your error go away, it is important to understand when to use static methods, variables, properties versus instance ones. In fact, you could say that using static members is not really a pure OOP practice. Most of the time, static members are misused because people misunderstand these OOP basics.
Static methods and variables are shared amongst all object instances for your class. Therefore, in most scenarios, you will need to have a specific requirement to have a static method/variable, such as keeping a total count of objects in a static variable which would be accessible across all your object instances.
You can create a new instance of the class where variables are.
public class YourClass
{
public string _string1 { get; set; }
public string _string2 { get; set; }
...
}
public static string Example()
{
YourClass yourClass = new YourClass();
switch(_string1.length > _string2.length)
{
case true :
return yourClass._string1;
break;
default : return yourClass._string2;
}
}
I'm writing an application in C#, which supports plugins. Each plugin has to introduce itself, such that application can prepare appropriate environment for it. The current info object looks more less like this:
class FilterInfo
{
public InputInfo[] inputs;
public OutputInfo[] outputs;
bool IsConfigurable;
bool IsPlayable;
string TypeName;
}
This structure will surely expand in future (however, I guess, that not much, it'll maybe double its size). I'm currently thinking on how to implement such info class properly.
In C++ I would do it the following way (I'll strip the class to one field to make the examples more readable):
class FilterInfo
{
private:
std::vector<const InputInfo> inputs;
public:
std::vector<const InputInfo> & GetInputs()
{
return inputs;
}
const std::vector<const InputInfo> & GetInputs() const
{
return inputs;
}
}
Now, the plugin would instantiate a FilterInfo class, fill-in its fields and then return const FilterInfo on request, such that noone may change contents of the info (well, noone should).
In C#, I can only imagine the following "safe" solution:
public interface IInputInfo
{
bool SomeData
{
get;
}
}
public class InputInfo : IInputInfo
{
private bool someData;
public bool SomeData
{
get
{
return someData;
}
set
{
someData = value;
}
}
public bool IInputInfo.SomeData
{
get
{
return someData;
}
}
}
public interface IFilterInfo
{
ReadOnlyCollection<IInputInfo> Inputs
{
get;
}
}
public class FilterInfo : IFilterInfo
{
private InputInfo[] inputs;
public InputInfo[] Inputs
{
get
{
return inputs;
}
set
{
inputs = value;
}
}
public ReadOnlyCollection<IInputInfo> IFilterInfo.Inputs
{
return inputs;
}
}
The plugin will, of course, return IFilterInfo instead of FilterInfo, such that the data is readonly (OK, I know about reflection, the matter is to notify the user, that the data should not be changed). However, this solution looks very clumsy to me - especially when compared to compact version I cited earlier.
Another solution may to be create FilterInfo only with getters, but it would require passing the data into it in some way and probably would end up with a huge constructor with lots of parameters.
Edit: Another solution is to create a struct and return its copy during every request. However, arrays are copied by reference, so I would have to copy them manually each time.
Yet another one is to construct the FilterInfo from the scratch each time anyone requests it, eg.
public FilterInfo Info
{
get
{
return new FilterInfo()
{
IsConfigurable = true,
IsPlayable = false,
Inputs = new[]
{
new InputInfo()
{
// (...)
}
}
}
}
}
Is there an elegant way to solve this problem?
I think you got it almost right the first time:
Define a public IFilterInfo interface in the pluggable assembly that only allows reading.
Implement the interface in a FilterInfo class in the plugin assembly that has internal setters on its properties.
Have a method return a new instance of the FilterInfo class upon request. Convention suggests to use a method instead of a property in cases where a new instance is constructed each time. (If you insist on using a property you could store the instance once it has been constructed and return it through the property)
Example:
In the pluggable assembly:
public interface IFilterInfo {
bool IsPlayable { get; }
bool IsConfigurable { get; }
}
In the plugin assembly:
internal class FilterInfo : IFilterInfo {
public bool IsPlayable { get; internal set; }
public bool IsConfigurable { get; internal set; }
}
public IFilterInfo GetFilterInfo() {
return new FilterInfo() { IsPlayable = true, IsConfigurable = false };
}
Internal setters and a read-only interface should be enough to ensure that the properties aren't modified outside the plugin assembly.
What about setting the setters to private or protected.
public class FilterInfo
{
public InputInfo[] inputs { get; private set; }
public OutputInfo[] outputs { get; private set; };
bool IsConfigurable;
bool IsPlayable;
string TypeName;
public void SetInputs(...)
{
InputInfo[] allInputs;
//do stuff
inputs = AllInput;
}
public void SetOutputs(...)
{
OutputInfo[] allOutputs;
//do stuff
outputs = AllOutput;
}
}
You would be able to have internal methods to set the data or go protected and allow modifying the objects through inheritance.
UPDATE
What about using the internal accessor for the setter. This way nothing will be able to access the setter unless it is declared in the InternalsVisibleTo assembly level attribute, which would be defined in the assembly containing FilterInfo.
The following post gives a good explanation on how to do this using the internal keyword.
Internal Description
UPDATE
Another solution may to be create FilterInfo only with getters, but it would require passing the data into it in some way and probably would end up with a huge constructor with lots of parameters.
According to this the only issue with not having a getter is that you still need to pass in data. The original solution allows this to happen. I guess I might be a little confused. If the plugin is able to change the information in this API which is by reference I am guessing. Then if the application is referencing the same assembly, it too would have the same accessors provided to the plugin. It seems that short of setting the setters to internal and allowing access through attributes would be the only way to achieve that type of functionality. But that wont work in your case because you do not know the assemblies that are referencing your API.
I don't quite sure about what you really want, but it seems the builder pattern is good for this case.
First, the setter or constructor can be marked internal, means that only the assembly can access the constructor or setter. Leave the getter public, it is needed, isn't it?
Then your builder class (assume you are using the constructor injection):
public class FilterInfoBuilder{
public FilterInfoBuilder(InputInfo[] inputInfo){
this.inputInfo = inputInfo;
}
private InputInfo[] inputInfo;
public FilterInfo Create(){
FilterInfo filterInfo = new FilterInfo(inputInfo);
return filterInfo;
}
}
Maybe I misunderstand your requirement though.
EDIT
You can tweak the builder as a dynamic setter though. Now consider using internal setter instead of internal constructor.
public class FilterInfoBuilder{
public FilterInfoBuilder(InputInfo[] inputInfo){
filterInfo = new FilterInfo();
filterInfo.InputInfo = inputInfo;
}
private FilterInfo filterInfo;
public FilterInfo FilterInfo{
get{
return filterInfo;
}
}
public void ChangeInputInfo(InputInfo[] inputInfo){
filterInfo.InputInfo = inputInfo;
}
}
You can use FilterInfoBuilder.FilterInfo to access the FilterInfo class. To modify it, you can create internal methods inside the builder class.
I don't really sure about the solution though, as I haven't found the design in any documented source.
More EDIT
I have another design, only if you can separate the interface between assemblies and make sure the application access the interface and not the class.
example:
public interface IInputInfoSetable{
public InputInfo[] InputInfo{
set;
}
}
public interface IFilterInfo{
public InputInfo[] InputInfo{
get;
}
}
public class FilterInfo: IFilterInfo, IInputInfoSetable{
// implement explicitly both of the interface.
}