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; }
Related
Ive got a mongo database set up and if its designed to use strongly typed objects:
public class Message : IDatabaseObject
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
[DataMember]
public string MessageBody { get; set; }
}
The class and all properties need to be public for MongoDB to use it as an object
I was about to make a factory to create a new instance as opposed to creating an instance of Message (duplicating code) each time but then I realised there would be more than one way to create a Message.
Is there a way to prevent direct instantiation of the data object outside of the assembly?
You can't make a private or internal property for serialization in mongo, but you can make the setter of property private or internal (mongo c# driver will take care of private setters for serializing and deserializing).
Make the constructor and setters internal or private (based on your use-case)
public class Message
{
[DataMember]
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; internal set; }
[DataMember]
public string MessageBody { get; internal set; }
internal Message() { }
}
public static class MessageFactory
{
public static Message Create()
{
return new Message();
}
}
You can expose a public factory method like DatabaseObjectFactory.Create<Message>() or Message.Create(), while keeping the constructor internal or even private.
If it is enough that during compile time you can't instanciate the class, Fody might be what you want. Specificially Publicize.Fody.
It allows you to write your class as internal. Compile it. Then have it run as a public class.
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 would like to be able to pass a known type to a general function but I'm getting compile errors because I can't cast the type at design time.
Consider my OnCreate function:
EXAMPLE 1:
private void OnCreate<T>(T object)
{
object.CurrentDate = DateTime.Now;
object.SpecialProperty = "Hello";
}
EXAMPLE 2:
private void OnCreate<T>(T object)
{
object.BirthDate = DateTime.Now;
object.BirthdayMessage = "Happy Birthday";
}
I want to call OnCreate and pass to it an object. That object happens to be a model object in an MVC application. I can't predict what model object is being passed to OnCreate yet I want to access the unique properties of the model that is passed. As my examples show above, one model has a CurrentDate and a SpecialProperty property; another has a BirthDate and a BirthdayMessage property. I don't want to create a special function for each because I have many different models. Also, this OnCreate function is going to get inherited from a base class. The idea here is to provide a "hook" into the controller's Create method so that someone can alter the model properties before they are persisted to the database. In other words, the controller's Create method would pass the model to my OnCreate function, then some work would be done on the model before it's passed back.
As you would expect, each model has different properties. Due to this requirement, I realize that I won't be able to early-bind and get intellisense with the OnCreate function--but my problem is that the compiler won't let me refer to properties of the object until it knows the object type. I can't cast it at design-time because I don't know the type until run-time.
EDIT
I think my question wasn't so clear, judging by the answers (for which I'm grateful--they're just not what I'm looking for). Perhaps it's better to show how I want to call OnCreate():
OnCreate(model);
Now, when OnCreate receives object "model", it needs to be able to set properties on that model. I suppose I could use reflection on the model and do something like this (this is pseudocode only--still learning about reflection):
if typeof(model) is CustomerModel then
(CustomerModel(model)).BirthDate = "1/1/1960";
(CustomerModel(model)).BirthdayMessage = "Happy Birthday";
elseif typeof(model) is AnotherModel then
(AnotherModel(model)).CurrentDate = DateTime.Now;
(AnotherModel(model)).SpecialProperty = "Hello";
etc...
But I am trying to avoid having a bunch of if/then statements. I prefer if the call could be "routed" to a function that's specific for the type being passed. That way, the call to OnCreate would send the object to an overload(?) so that no reflection logic is needed...
SECOND EDIT
Upon further reflection (no pun intended), I don't think having a bunch of if/else statements in the OnCreate function is the best approach here. I came up with another idea that might work best and accommodates my expressed wish to "avoid having a bunch of if/then statements" (specified in my first Edit): The idea is to have my models implement IOnCreate, which would provide the .OnCreate() method. Thus, my "generic" model objects that implement IOnCreate could be used this way:
model.OnCreate();
Then the OnCreate function would know what properties are on the model:
public void OnCreate()
{
this.BirthdayMessage = "Happy Birthday";
etc...
}
I just see two issues here:
1 - In the controller I would need to test that the model implements IOnCreate--if it doesn't, I wouldn't try to call OnCreate().
2 - I need to be sure that adding a public function such as OnCreate() will not interfere with how EF6 generates database tables in a code-first project.
My question now is whether this approach be best... or whether there is any other idea to consider...
Since T is any type, compiler can't expect it having CurrentDate or SpecialProperty;
you could try solving the problem like that:
public interface IMyInterface {
DateTime CurrentDate {get; set}
String SpecialProperty {get; set}
}
public class MyClassA: IMyInterface {...}
public class MyClassB: IMyInterface {...}
public class MyClassC: IMyInterface {...}
...
private void OnCreate<T>(T value)
where T: IMyInterface // <- T should implement IMyInterface
{
value.CurrentDate = DateTime.Now;
value.SpecialProperty = "Hello";
}
By your example it seems unlikely the Generics are the the solution for you problem (your app), it would seems that a use of an abstract layer (Interface or Abstract Class) is more appropriate.
When using "bare bone" generics any Type can be passed to your method, now since any type in .Net is of type Object you can execute any object related functionality on those generics parameters. To extend this ability of the generics to implements the most basic type in the inheritance hierarchy we have Generics Constraints, those allow you to limit the range of types that can be passed as a generic argument. In your case you'd want to use Type Constraints, which limit the range of types to only those which implement the type specified.
For example, we have type A, and the A has types B and C as derived classes, we want method M to accept only type how implements A:
class Program
{
static void Main(string[] args)
{
M(new A()); // will work
M(new B()); // will work
M(new C()); // will work
M(new D()); // wont work
}
public static string M<T>(T arg)
where T : A
{
return arg.Data;
}
}
public class A { public string Data { get; set; } }
public class B : A { }
public class C : B { }
public class D { }
Edit
According to your last edit it would seems that you have two options to solve this problem.
Implementing an abstraction layer (an Interface): You may want to add an interface and implement it by your models.
public static void OnCreate(IBirthable arg)
{
arg.BirthDate = ...;
}
Interface:
public interface IBirthable
{
DateTime BirthDate { get; set; }
string BirthdayMessage { get; set; }
}
Models:
public class CustomerModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
Using reflection: If you choose not to use an interface, perhaps is has no logical connection with your models you may want use reflection.
public static void OnCreate<T>(T arg)
{
var type = arg.GetType();
var birthDateProperty = type.GetProperty("BirthDate");
if (birthDateProperty == null)
throw new ArgumentException("Argument not is implementing the model");
birthDateProperty.SetValue(arg, DateTime.Now);
//And so on...
}
Models:
public class CustomerModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
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).
Total OO noob question here. I have these two methods in a class
private void StoreSessionSpecific(LateSession dbSession, SessionViewModel session)
{
session.LateSessionViewModel.Guidelines = dbSession.Guidelines.ToList();
}
private void StoreSessionSpecific(Session dbSession, SessionViewModel session )
{
// nothing to do yet...
}
And when I call StoreSessionSpecific with dbSession being of type LateSession (LateSession inherits Session)
var dbSession = new LateSession();
StoreSessionSpecific(dbSession, session);
I expected the top one to be called. Since dbSession is of type LateSession.
#Paolo Tedesco This is how the classes are defined.
public class Session
{
public int ID { get; set; }
public int SessionTypeId { get; set; }
public virtual SessionType SessionType { get; set; }
[Required]
public DateTime StartTime { get; set; }
[Required]
public DateTime EndTime { get; set; }
// Session duration in minutes
// public int SessionDuration { get; set; }
public virtual ICollection<Attendee> Attendees { get; set; }
}
public class LateSession : Session
{
public int MaxCriticalIncidentsPerUser { get; set; }
public int MaxResultCriticalIncidents { get; set; }
public virtual ICollection<Guideline> Guidelines { get; set; }
}
Well, your assumption is plausible and there are languages where it had worked like you thought.
So does your code look like this:
Session s = new LateSession(); // the compiler only "knows" that s is of type Session
StoreSessionSpecific(s);
or does it look like this:
LateSession ls = new LateSession(); // the compiler knows that ls is in fact a LateSession
StoreSessionSpecific(ls);
In the first example the compiler prettends not to know what the actual type of "s" is and hard codes the invocation of the method with the Session argument.
In the second example likewise the compiler generates a hard coded call to the other method.
In other languages the method call is "dynamic", that means during runtime the actuall types are considered. Methods that are polymorphic on their arguments are called "multimethods" (They are not only polymorphic on the class they are defined in but also on the arguments, hence "multi")
(Edit: fixed typos)
I think the problem is somewhere else in your code. If you try this example, things work as expected:
class Base {
}
class Derived : Base {
}
class Something {
private void DoSomething(Base b) {
Console.WriteLine("DoSomething - Base");
}
private void DoSomething(Derived d) {
Console.WriteLine("DoSomething - Derived");
}
public void Test() {
var d = new Derived();
DoSomething(d);
}
}
static class Program {
static void Main(params string[] args) {
Something something = new Something();
something.Test();
}
}
Could you post a complete example? maybe there's a problem with the class definitions...
I apologize for not knowing the specifics of why this happens, but I have an idea on how to work around it.
Try loosing the (LateSession, SessionViewModel) overload, and account for LateSession in the (Session, SessionViewModel) overload like:
private void StoreSessionSpecific(Session dbSession, SessionViewModel session )
{
if (dbSession is LateSession) {
// handle as LateSession
} else {
// handle as base-class Session
}
}
As Angel O'Sphere said, C# doesn't have multiple dispatch however you can implement double dispatch using Visitor Pattern.
http://en.wikipedia.org/wiki/Visitor_pattern
What is the type of dbSession after that assignment? I would assume it is what you expect, but it could be a Session.
Separately, do you really need to overload this method with both a child and parent class? It seems like a strange case where you would need both, and will likely lead to confusion.