What is the difference this oop patterns pros and cons? - language-agnostic

i writed some codes about oop pattern. But i cannot see clearly these two kind of usage advantage disadvantagages:
Firs one:
class Program
{
static void Main(string[] args)
{
Report rp = new Report();
rp.MakeReport();
rp = new ExcelReport();
rp.MakeReport();
rp = new PdfReport();
rp.MakeReport();
rp = new WordReport();
rp.MakeReport();
Console.ReadKey();
}
}
Second usage
class Program
{
static void Main(string[] args)
{
Report[] rp = new Report[4];
rp[0] = new Report();
rp[1] = new ExcelReport();
rp[2] = new PdfReport();
rp[3] = new WordReport();
rp[0].MakeReport();
rp[1].MakeReport();
rp[2].MakeReport();
rp[3].MakeReport();
Console.ReadKey();
}
}
Class stracture:
class Report
{
public virtual void MakeReport()
{
Console.WriteLine("Simple Report preparing...");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Simple Report prepared...");
}
}
class ExcelReport : Report
{
public override void MakeReport()
{
Console.WriteLine("Excel Report preparing...");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Excel Report prepared...");
}
}
class PdfReport : Report
{
public override void MakeReport()
{
Console.WriteLine("Pdf Report preparing...");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Pdf Report prepared...");
}
}
class WordReport : Report
{
public override void MakeReport()
{
Console.WriteLine("Word Report preparing...");
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Word Report prepared...");
}
}
What is the difference first one and second one? which one can i prefer ? what kind of stuation can i use one of them? What is adv or disAdv between two kind of usage?

The disadvantage of the second one is that explicit indexes are hard to maintain (come back later and modify), or even to copy-paste-modify. A typo will be very hard to find, and won't generate a compiler error.
Instead of either of these, you may want to consider doing a more common polymorphic practice: iterating over a list/array of the base type. A big advantage of this is that the code can be formatted to be both very brief, and easy to read.
class Program
{
static void Main(string[] args)
{
Report[] reports = new Report[]
{
new Report(),
new ExcelReport(),
new PdfReport(),
new WordReport(),
};
foreach(Report report in reports)
report.MakeReport();
Console.ReadKey();
}
}
Also, in many cases, collection classes are more flexible/convenient than arrays. For example, you can add new values at a later time to a List<Report>:
class Program
{
static void Main(string[] args)
{
List<Report> reports = new List<Report>()
{
new Report(),
new ExcelReport(),
new PdfReport(),
new WordReport(),
};
foreach(Report report in reports)
report.MakeReport();
report.Add(new ExcelReport());
foreach(Report report in reports)
report.MakeReport();
Console.ReadKey();
}
}

If you don't want to keep a reference to the report objects, you could do this:
class Program
{
static void Main(string[] args)
{
new Report().MakeReport();
new ExcelReport().MakeReport();
new PdfReport().MakeReport();
new WordReport().MakeReport();
Console.ReadKey();
}
}

I don't see any difference between the two.
If you want to fire-and-forget a report, use the first one. If you want to hold on to your report objects for some other calls, cache them in an array as in the second case. Not much difference really.

Related

how to maintian the EF connection string at one place?

I have the following in my project solution,am trying to maintain the Database connection of Entity framework at one place so that if I have to switch the database to a different vendor(like MYSQL to MSSQL or vice-versa) I can just change the connection name at one place and doesn't have to change at all the places...I tried the following structure but running into an error,how to fix it?
Project#1
Dashboard.EntityFramework
-->bitDbConnection.cs
using
namespace Dashboard.EntityFramework
{
public class bitDbConnection
{
BitDatabaseEntities bitDB = new BitDatabaseEntities();
}
}
Project#2
Dashboard.Repository
-->Repository.cs
using Dashboard.EntityFramework
when I try use to bitDB variable I can the below error
Error:-
The name bitDB does not exist in current context
This probably isn't what you want but to get your code to work, write it like this:
namespace Dashboard.EntityFramework
{
public class bitDbConnection
{
public BitDatabaseEntities bitDB = new BitDatabaseEntities();
}
}
using Dashboard.EntityFramework
public class Repository
{
public void DoSomething()
{
var bitDB = new bitDbConnection().bitDB;
}
}
So, first make bitDB field public, and then use it...
edit for question in comments:
public class Repository
{
private BitDatabaseEntities bitDB = new BitDatabaseEntities().bitDB;
public void DoSomething()
{
var x = bitDB.ToString();
}
}

Azure WebJob- QueueTrigger Staging and Production

I have an Azure WebJob that will be used for Staging and Production. The keys for the proper environments are set in the app.config file.
A ConfigManager class reads the properties from the app.config file.
public static string FirstQueue
{
get { return ConfigurationManager.AppSettings["FirstQueue"]; }
}
I would like the QueueTrigger to read the from the proper queue specified in the app.config file.
public static void ProcessFirstQueue([QueueTrigger(ConfigManager.FirstQueue)] string message)
{
//some function
}
However, the QueueTrigger doesn't seem to like this. I get "An attribute argument must be a constant expression, type of expression...." Any suggestions to set this up. I do not want to hard code values in the queue trigger.
Thanks
You can resolve the queue name at runtime using the
INameResolver
Here's an example to demonstrate this:
WebJob Code:
public class Program
{
private static void Main(string[] args)
{
var config =
new JobHostConfiguration("insert connection string")
{
NameResolver = new QueueNameResolver()
};
var host = new JobHost(config);
host.RunAndBlock();
}
public static void ProcessNotification([QueueTrigger("%queueKey%")] string item)
{
//Handle message
}
public static void ProcessPoison([QueueTrigger("%queueKeyPoison%")] string item)
{
//Handle poison message
}
}
Here's the QueueNameResolver class:
public class QueueNameResolver : INameResolver
{
//name = queueKey or queueKeyPoison
public string Resolve(string name)
{
//Use the name to get it from the app.config or somewhere else.
}
}
Hope this helps,

JerseyServlet doesn't save object in memory

since I was sitting the whole day and could not figure out the problem, I am hoping you can help me.
Here you can see a Jersey service class. This class should simply store teams, and you can add and retrieve teams.
#Path("/jsonServices")
public class JerseyRestService {
Tournament tournament = new Tournament();
#POST
#Path("/send")
#Consumes(MediaType.APPLICATION_JSON)
public Response consumeJSON(Team team) {
tournament.addTeam(team);
return Response.status(200).entity(team.toString() + tournament.teams.size()).build();
}
#GET
#Path("/print/{name}")
#Produces(MediaType.APPLICATION_JSON)
public Team produceJSON(#PathParam("name") String name) {
return tournament.getTeam(name);
}
}
public class Tournament {
List<Team> teams = new ArrayList<Team>();
public boolean addTeam(Team student) {
return teams.add(student);
}
public Team getTeam(String name) {
System.err.println("Halleluja");
return teams.get(0);
}
}
I am adding teams with a simple client:
public class JerseyPost {
private static Client client;
private static WebResource webResource;
private static ClientResponse response;
public static void main(String[] args) {
try {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
client = Client.create(clientConfig);
webResource = client.resource("http://localhost:8080/JerseyJSONExample/rest/jsonServices/send");
webResource.accept(MediaType.APPLICATION_JSON);
response = webResource.type(MediaType.APPLICATION_JSON).post(ClientResponse.class, new Team("1", "Batman1","Robin1"));
if (response.getStatus() != 200) {
throw new RuntimeException("Failed: HTTP error code: " + response.getStatus());
}
System.out.println(response.getEntity(String.class));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Unfortunetly the teams are not saved. After I add a team the list size is always just one.
When I try a GET request the list is always empty.
Thank you very much, for any help you can prvide me.
Regards Robert
Refer here Jersey creates new instance of Resource class for every new request.
Resource class (JerseyRestService in your case)
By default the life-cycle of root resource classes is per-request
which, namely that a new instance of a root resource class is created
every time the request URI path matches the root resource. This makes
for a very natural programming model where constructors and fields can
be utilized (as in the previous section showing the constructor of the
SparklinesResource class) without concern for multiple concurrent
requests to the same resource.
So tournament.addTeam(team); you populate here will be available only for consumeJSON method
to solve your problem make 'tournament' as static so that it will be shared across all the instance
static Tournament tournament = new Tournament();
Hope that helps

Linq's DataContexts and "Unit of Work" pattern. Is my approach ok?

Following the directions from many articles, I've decided to implement the Unit of work pattern to my Linq2SQL DataContexts in my ASP.Net WebForms Application, but I'm not sure if I'm on the right way.
Here's what I'm accomplishing so far:
1 - On every Request, I catch the Application_AcquireRequestState event (which has access to Session data) in Global.asax and instantiate a new DataContext to bind it to the user's Session:
void Application_AcquireRequestState(object sender, EventArgs e)
{
// Check if the request is for a Page, Page Method or Handler
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Session["myDatabaseDataContext"] = myDatabaseDataContext;
}
}
2 - Every Data Access Layer Object (DAO) inherits from a base DAO: GenericDAO:
public class GenericDAO
{
private MyDatabaseDataContext _dbMyDatabase;
protected MyDatabaseDataContext dbMyDatabase
{
get
{
if (_dbMyDatabase == null)
_dbMyDatabase = HttpContext.Current.Session["myDatabaseDataContext"] as MyDatabaseDataContext;
return _dbMyDatabase;
}
}
}
3 - So, in every operation, the DAO use the DataContext Property from its parent class:
public class MyTableDAO : GenericDAO
{
public List<MyTable> getAll()
{
return dbMyDatabase.GetTable<MyTable>().ToList();
}
}
Here's my concerns...
First of all, is it ok to store the DataContext in the user's Session? What would be another option? My app has a lot of PageMethods calls, so I'm worried the DTX would be invalidated between their async requests if it is stored in the session.
Do I need to capture the Application_ReleaseRequestState event to Dispose() of the DataContext and remove it from the session?
If I don't need to Dispose of it, in every Application_AcquireRequestState, would it be better to Remove DTX from Session - Create DTX - Store it or just Refresh it?
Also, if I don't need to Dispose of it, what about Connections? Would it handle them automatically or I would need to control them too?
I appreciate your time and help :)
-- EDIT
Here's the code I've reached, following #ivowiblo's suggestion:
Global.asax
void Application_BeginRequest(object sender, EventArgs e)
{
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
MyCompany.MyDatabaseDataContext myDatabaseDataContext = new MyCompany.MyDatabaseDataContext();
HttpContext.Current.Items["myDatabaseDataContext"] = ceabsDataContext;
}
}
void Application_EndRequest(object sender, EventArgs e)
{
if (new Regex(#"\.(aspx|ashx)(/.*)?$").IsMatch(HttpContext.Current.Request.Url.AbsolutePath))
{
if (HttpContext.Current.Items["myDatabaseDataContext"] != null)
{
System.Data.Linq.DataContext myDbDtx = HttpContext.Current.Items["myDatabaseDataContext"] as System.Data.Linq.DataContext;
if (myDbDtx != null)
myDbDtx.Dispose();
}
}
}
GenericDAO
public class GenericDAO
{
protected MyDatabaseDataContext dbMyDatabase
{
get
{
return HttpContext.Current.Items["myDatabaseDataContext"] as MyDatabaseDataContext;
}
}
}
Simple as that!
The best approach is to put it on HttpContext.Current.Items, creating the DataContext on RequestBegin and dispose it in RequestEnd. In msdn there's an interesting article about the better management of the DataContext, where it's suggested to have short-time DataContext instances.
This pattern is called Open session in view and was created for using NHibernate in web environments.
You say you are implementing unit-of-work, but by storing it in the cache you do not really stick to that unit-of-work.
My advice is to create a new DataContext for every request and not to cache it anyware.

Ordered resolution of types from Castle Windsor AllTypes

I have a group of classes that implement an interface for my application start-up activities. Here is the registration code:
private static void ConfigureContainer()
{
var container = new WindsorContainer();
container.Register(AllTypes.Of<IStartupTask>()
.FromAssembly(Assembly.GetExecutingAssembly()))
...
var serviceLocator = container.Resolve<IServiceLocator>();
ServiceLocator.SetLocatorProvider(() => serviceLocator);
}
In order to get the tasks, I use this and it works as expected:
public static void Run()
{
var tasks = ServiceLocator.Current.GetAllInstances<IStartupTask>();
foreach (var task in tasks)
{
task.Execute();
}
}
Here is my problem: I have one task that depends on another being run first. There is an InitializeDatabase task that needs to run before the PopulateDatabse task. There are also a bunch of other tasks that are run and I would rather not split the InitializeDatabase task out, if there is some Castle config that will allow me to order the resolution of the types. I don't want to specify the complete order of the types being resolved since that defeats the purpose of the automatic registration, just that InitializeDatabase is the first or PopulateDatabase is last.
Is there a way to register which types should be resolved first without specifying the order of all the types?
Here's one way to do it, it might not be very pretty but it works:
[AttributeUsage(AttributeTargets.Class)]
public class FirstAttribute: Attribute {}
public interface IService {}
public class ThirdService : IService { }
[First]
public class FirstService : IService { }
public class SecondService: IService {}
[Test]
public void WindsorOrder() {
var container = new WindsorContainer();
container.Register(AllTypes.Of<IService>()
.FromAssembly(Assembly.GetExecutingAssembly()));
var intf = container.ResolveAll<IService>()
.OrderByDescending(i => i.GetType().GetCustomAttributes(typeof(FirstAttribute), true).Length)
.ToArray();
Assert.IsInstanceOfType(typeof(FirstService), intf[0]);
}
If you remove [First] from FirstService, the first will be ThirdService and the test will fail.
Use HandlerSelector for that