Related
Following is my ASP.Net Web API controller code. Here as you can see there's a private class object, BL, that is used and both the Get methods implemented. For the first method FetchAllDashboardByUserId(int userId), I pass the user id so that the BL object can be initiated. Within the same browser session, if the second get method is called, then I do not want to pass the userid, since BL should be by default initiated, but currently that's not the case. BL is null for the second method, so I have to add userid to the call to the method - GetCardDataUI(int userId, int dashBoardID, int cardID). My question is how to avoid it. Is my thinking incorrect that:
A single open browser where I make the Consecutive call to the following URLs are a single session:
webapi/ViewR?userId=1
webapi/ViewR?userId=1&dashBoardID=1&cardID=3
I don't want to pass the userId in the second URL. Please note that if I declare class object as static then it works as expected, but that's not what I want, it has to be tied to a user:
public class ViewRController : ApiController
{
// BL object for a user
private static BL accessBL = null;
// HTTP GET for Webapi/ViewR (Webapi - name of API, ViewR - Controller with implementation)
[AcceptVerbs("Get")]
public List<DashboardUI> FetchAllDashboardByUserId(int userId)
{
if (accessBL == null)
accessBL = new BL(userId);
// Use BL object for entity processing
}
[AcceptVerbs("Get")]
public CardDataGetUI GetCardDataUI(int userId, int dashBoardID, int cardID)
{
if (accessBL == null)
accessBL = new BL(userId);
// Use BL object for entity processing
}
}
How I want the second method implementation to be:
[AcceptVerbs("Get")]
public CardDataGetUI GetCardDataUI(int dashBoardID, int cardID)
{
// Use BL class object created in last call for entity processing
// Should not pass userid again
}
You can easily store data in Session:
... first request:
Session["userID"] = userID;
... next request:
int userID = (int)Session["userID"]; // should check for null first, but you get the idea...
But keep the following points in mind:
Session variables are stored as objects, so you'll need to cast and/or type-check
Session variables can be null
Session expires after a configurable (in web.config) about of time
Default session state is in-memory, meaning if the app pool is restarted session state is gone - you can store session in files or databases to keep longer
Session doesn't scale out unless you use persistent storage (file, database)
Objects stored in persistent storage must be serializable
Summary
I tried to achieve inheritance and encapsulation properly in javascript like it was in a class-based language such as c#.
The ugly part is the protected members have multiple copies in the private instances which are only accessible via closure, and I don't have an idea except refreshing those members to the private instances.
If it is possible, I want to get rid of both transmit and transfer in my code of Function.extend.
Update
For people who are interested in citing or research, here's the source code repository:
https://github.com/kenkins/Function.extend
The story
Since assemblies may be a concept which is out of range of javascript, I don't take the internal modifier into account, but public, protected and private.
public and private modifiers are not that difficult to achieve; but with inheritance, protected is significantly tricky. Yet it's not a recommended thing to do with javascript, most of articles I've read says prefix with a special character and document it.
But it seems I'm persisted to make javascript to simulate class-based languages .. I stole this idea and implemented in my way, the code is at rear of this post.
The idea behind the scene is to put higher accessibility with a higher prototype and access the highest one with a closure.
Say we have three prototypes A, D and G, it looks like
As it is not possible that an object is an instance of a type also of another type which is not in the prototype chain; the way I chosen is to chain the protected level horizontally and copy the members from the prototype of the declaring type. This makes nesting class possible, because the members declared on a less-derived type can be propagated to more-derived types; the transmit method in my code is to do this. If A, D and G have their own protected members, it would look like:
The closure for accessing the private instance, is this['']. It takes an argument which is for identifying a class. The modifiers holder is just the class identifier, named y in Function.extend and _ in the test code, it should not be exposed outside the class declaration. It is also used as a shortcut of this[''].
_['base'] is in fact not only the base constructor invoker, but also the private instances creator. It creates the private instances and updates this[''] for each constructor with the inheritance, so it should always be called in the constructors.
Although a private instance would have the access of the public members, it should not be used to alter them, since this[''] is not guaranteed to be invoked when accessing public members. But the accessing of private instance is; recent remembers the most recently accessed private instance, and update the protected members if there're changes.
My question is, how can I get rid of this kind of refreshing the protected members? Are there better ideas to achieve the encapsulation more of the realistic?
p.s.: I actually do not want a solution which uses non-standard methods/properties .. and it would be better there're polyfills if the used methods/properties are too fashion to the old browsers.
Function.extend
Function.extend=function(base, factory) {
factory.call(initializeClass);
updateStaticMembersOfDerivedInnerClasses(y['public'].constructor);
transfer(y['protected'], y['public']);
return y['public'].constructor;
function y($this) {
return $this[''](y);
}
function transfer(target, source, descriptor) {
if(target!==source?
'undefined'!==typeof target?
'undefined'!==typeof source:
false:false) {
var keys='undefined'!==typeof descriptor? descriptor:source;
for(var key in keys) {
if(Object.prototype.hasOwnProperty.call(source, key)) {
target[key]=source[key];
}
}
}
}
function updateStaticMembersOfDerivedInnerClasses(outer) {
var member, inner;
for(var key in outer) {
if(Object.prototype.hasOwnProperty.call(outer, key)?
(member=outer[key]) instanceof outer?
outer!==(inner=member.constructor):
false:false) {
transfer(inner, outer);
}
}
}
function initializeInstance() {
var $this=Object.create(y['private']);
var derivedGet=this[''];
var recent=$this;
this['']=function(x) {
var value=y!==x? derivedGet.call(this, x):$this;
if(value!==recent) {
transfer(value, recent, x['protected']);
recent=value;
}
transfer(value, this);
return value;
};
base.apply(this, arguments);
$this['']=this[''];
}
function initializeClass(derived) {
y['public']=Object.create(base.prototype);
y['public'].constructor=derived;
if(Object.prototype.hasOwnProperty.call(base, 'transmit')) {
base.transmit(y);
}
else {
y['protected']=Object.create(y['public']);
}
y['private']=Object.create(y['protected']);
y['base']=initializeInstance;
transfer(derived, base);
derived.transmit=function(x) {
if(x['public'] instanceof derived) {
x['protected']=Object.create(y['protected']);
x['protected'].constructor=x['public'].constructor;
}
};
derived.prototype=y['public'];
return y;
}
};
test code
'use strict';
var BaseClass=Function.extend(Object, function () {
var _=this(BaseClass);
var NestedClass=Function.extend(BaseClass, function () {
var _=this(NestedClass);
function NestedClass(x, y, z) {
_['base'].apply(this, arguments);
_(this).Y=y;
_(this).Z=z;
}
_['public'].SetX=function (x) {
_(this).InternalSetX(x);
};
_['public'].GetX=function () {
return _(this).InternalGetX();
};
_['public'].GetY=function () {
return _(this).Y;
};
_['public'].SetZ=function (z) {
_(this).Z=z;
};
_['public'].GetZ=function () {
return _(this).Z;
};
_['private'].Y=0;
});
function BaseClass(x) {
_['base'].apply(this, arguments);
_(this).X=x;
}
_['protected'].InternalSetX=function (x) {
_(this).X=x;
};
_['protected'].InternalGetX=function () {
return _(this).X;
};
_['private'].X=0;
_['protected'].Z=0;
BaseClass.Sample=new NestedClass(1, 2, 3);
});
var DerivedClass=Function.extend(BaseClass, function () {
var _=this(DerivedClass);
function DerivedClass(x, y, z) {
_['base'].apply(this, arguments);
}
});
var o=DerivedClass.Sample;
alert(o.GetX());
alert(o.GetY());
alert(o.GetZ());
o.SetX(3);
o.SetZ(1);
alert(o.GetX());
alert(o.GetY());
alert(o.GetZ());
I also had a similar thought and decided to try write something. A vanilla js solution. Still early but I like what came out of it. You might find it interesting also.
It's not exactly c# but provides a more strict ecosystem. And some other advanced js features in a lightweight solution.
https://github.com/iamlothian/rucksack.js
This is not a solution to your code, but solution to your concept. If your goal was the get your idea to work then by all means continue as I am interested by the result.
If you like me just want a more structured js environment, then here is one I wrote with similar ambition to your questions concepts.
Part 2:
The idea here is to use closure and access restriction to create a pattern that restricts the way code can be used and changed after is has been defined. For the most part a lot of the hard work has been done. But the pattern is left for you to define.
Here is a quick mock example demonstrating how you might implement a public|protect|private inheritance. I am trying to decide weather i implement some of this as a built in feature or leave it up to users to implement their own object extension like i have in the example.
http://plnkr.co/edit/ao2hTyBV1b3nYIwr7ZS5
The implementation is in scripts.js. view you console to see what is going on.
What rucksack provides is a framework for creating detached modules of code. These modules are grouped into namespaces and can depend on each other. These dependencies are resolved lazily as defined, so that definition order is not really important. The resolution process provides some other useful features such as interfaces matching and sealed module.
current features:
Modular
Dependency Injection
Factory constructor (Instances Object)
Service constructor (Static Objects)
Lazy loading
Easy error logging (All error within modules are captured and can be passed on)
Namespaces
Sealable modules and namespaces (modules that can't be accessed from outside the namespace)
Global await event for module
Interface for optional config object
Optional strict interface checks for injection
While the code with closure might solve what you want, I would go with the simpler Privileged methods as Crockford called them here.
Usage idea is simple:
Define privileged method on the base object (with limit 1 - allows to be called only once).
Privileged method returns a protected interface of itself (of a base object) which contains protected functions in it (probably those functions are privately defined in the base, and then get copied over to the protected interface object... or maybe the protected interface exists privately).
Each object extends its protected interface with its base object's protected interface and still exposes it through the privileged method.
You will end up with something like this:
function A() {
var protected = {
protectedA: function() { }
};
this.getProtected = (function() {
var allow = true;
//privileged function.
return function() {
if (allow) {
allow = false;
return protected;
}
};
});
}
//B - derives from (extends) A
function B() {
var base = {}; //acquiring a base omitted - depends on your implementation.
var protected = {
protectedB: function() { }
};
//"extend" simply copies new members into protected:
protected = $.extend(protected, base.getProtected());
this.getProtected = function() {
/* privileged function - similar to A.getProtected */
};
}
JavaScript has limited abilities in this extent, so the protected sugar comes with some cost anyway.
Javascript is a wide language, because you can do almost all the things do you want in a webpage, just by creating functions and finding ways to do it.
I can tell you that JavaScript are not a secure language, because you can easily access the most part of variables and functions, read them, and know how it works, just by acessing the .js file, included on the page.
My Tought: Some access modifiers was not created to use in javascript due to developers already know that maybe it can be useless, because JavaScript does not "Travel" into another places(pages), unless you use a session variable.
And about that modifiers:
Private
Protected
Public
I can tell you that i know some javascript modifiers that have some similarity to them, that are:
Local:
var Variable = 0;
Automatically, this is converted into a Integer variable, because it is receiving a Integer value, and too, this is a LOCAL variable because of the var modifier that declare this variable in a way that you cannot access the value of it, unless if you are inside the same function that this variable was declared.
Example:
If you declare these functions this way, with default modifiers:
function conflict(){
i = 2;
changeI();
alert(i);
}
function changeI(){
i = 0;
}
In this case the i is the same variable for the two functions.
So if you execute conflict(); you will get a alert resulting 0.
BUT, if you declare i using the var modifier:
function conflict(){
var i = 2;
changeI();
alert(i);
}
function changeI(){
var i = 0;
}
In this case, you have two i variables, because they are restricted to use only inside their function, so if you execute conflict(); now, you will get a alert with value of 2.
Class Variable:
this.Variable = "a";
This variable is automatically a String, because it is receiving a String value, Probably you already know what the this modifier does, but, i'll try to explain with my point of view, that is this variable is coming from the SuperClass or in javascript a "SuperFunction" that can be called a Class, or in other words, the "father" class.
A example:
function TClass()
{
this.getVar = function()
{
try
{
return "test";
}
catch(err)
{
return false;
}
}
this.alertVar = function()
{
try
{
alert(this.getVar());
}
catch(err)
{
alert('error');
}
}
}
var $Class = new TClass();
As you see above, i created a Class TClass and some variables containing functions into it (javascript closure) and added the modifier this. to them, to make them bound to the TClass and as you see on the alertVar() function, i access on the alert(this.getVar()); the function that are from the TClass that is equal to this in this context.
And this part: var $Class = new TClass(); i am creating the class as you probably knew that, to have access to its methods, doing this i am possible to execute, to test:
$Class.alertVar();
And getting as result, an alertbox containing "test", as you can see:
Note that you can't access the TClass methods in another ways, you only can access it creating the class and accessing by it.
So i hope that you did understand the usability of the this modifier.
Global:
window.Variable = true;
Automatically javascript declare this variable is a boolean, because it is receiving a Boolean value. The window modifier as it says, you can access it whatever you are on the window that you are, because javascript variables when declared, they go to the DOM into the window, see what is DOM:
DOM(Document Object Model): The DOM, is a multi-platform that represents how the html,xhtml, and xml markup's are organized and read by the browser that you are using. In other words, if you access the DOM you can see every propery, every variable, or such of thing that exists on the browser at the moment.
Different from another variables, the window variables can have assigned another value and access the actual value, from whatever you are, inside a function or not, inside a js file or not.
Example of Global(window):
Execute on the onLoad event of a page a code that declares a window variable, or declare it yourself using browser console:
window.Variable = true;
Then, add a JS File containing this function, or create it yourself just by executing the code on the browser console:
function testGlobalVar(){
if (Variable)
alert("it works!");
}
When you execute testGlobalVar() you will get the alert, but it is only because you declared it as `window´ otherwise, you will get nothing.
Default Modifier:
Variable = 0.5
Automatically this Variable is declared as Float beacuse it is receiving a Float value. I dont know if you already know, but javascript variables declared as the usual way, have a default modifier that makes the variable similar to window variables, but you cannot access it from whatever you are, but in most cases you can acess it, particulary, i dont know all the cases that you cannot access it, but i know that you cant when you loaded a js file and it was declared inside it. Only if you run a function that declares it, and after that try to acesss.
By the way, i see that you want to know modifiers that match the three that you said, but at my tought some of that modifiers that i told you can be used to do the same that your c# modifiers do.
I hope that you understand what i'm saying.
Ah, and if you was confused when you saw a function inside a variable, study Javascript Closures, you will understand after that :).
How the parent and child classes interact with each other
An extending child class calls super.call, a function that constructs an instance of it's parent.
A parent class shares it's protected members (both fields and functions) to it's extending subclass by using this.share in it's constructor.
A subclass can also call super.fetch(), which returns the object of fields/functions that the parent class passed to this.share
To illustrate my technique, the following code demonstrates some essentials to OOP with a simple example of a class Dog extends Animal
Some core functions for this object oriented model
// runs in both node.js and browser
var global_namespace = ('undefined'==typeof module)? window: global;
// put a no-operation function in the value for `share` in case nothing is extending a class
var not_extendable = {share:function(){}};
// when something is extending a class...
var extendable = function(constructor) {
// create a space for protected fields
var protected_space = {};
// the following is what will get passed as `this` to the parent constructor
var sharing = {
share: function(fields) {
protected_space = fields;
},
};
// the following is what will get passed as the first arg to the child constructor
return {
// enables child to call its parent's constructor
call: function(args) {
return constructor.apply(sharing, args);
},
// allows child to access protected fields shared by its parent
fetch: function() {
return protected_space;
},
};
};
Animal class
// class definition for `Animal`
(function(namespace) {
// construct an instance of this class
var constructor = function(name, weight, info) {
// private fields
var color = (info && info.color) || 'unknown';
// for protected fields
var protect = {
weight: weight,
noise: function() {
return 'nothing';
},
};
// share the protected fields with any subclass that might be extending this
this.share(protect);
// public fields and methods
return {
speak: function() {
console.log(name+' says '+protect.noise());
},
feed: function() {
console.log(name+' is not hungry');
},
weigh: function() {
console.log(name+' weighs '+protect.weight+' lbs');
},
toString: function() {
return '{Animal}';
},
};
};
// handle calls to: `Animal()`
namespace.Animal = function() {
// called with new operator: `new Animal(...)`
if(this !== namespace) {
// construct simple instance of this class
return constructor.apply(not_extendable, arguments);
}
// static call: `Animal(...)`, means the caller wants to extend this class
else {
// reference child constructor
var child_constructor = arguments[0];
// return a wrapped constructor function
return function() {
// call child constructor and allow it to call the super constructor
return child_constructor.apply({}, [extendable(constructor), arguments]);
};
}
};
})(global_namespace);
Dog class
// class definition for `Dog`
(function(namespace) {
// class `Dog` extends class `Animal`
var constructor = Animal(function(super_class, args) {
// private field
var been_fed = false;
// call super's constructor
var operator = super_class.call(args);
// inherit parent's protected members
var parent = super_class.fetch();
// override a protected method
parent.noise = function() {
return 'bark!';
};
// override a public method
operator.feed = function() {
been_fed = true;
parent.weight += 5;
};
// extend a public method
var super_weigh = operator.weigh;
operator.weigh = function() {
super_weigh();
if(been_fed) console.log('\t'+args[0]+' has been eating :)');
else console.log('\t'+args[0]+' has not been fed yet');
};
// override another public method
operator.toString = function() {
return '{Dog}';
},
// return the operator (interfacable instance object)
return operator;
});
// handle calls to: `Dog()`
namespace.Dog = function() {
// called with new operator: `new Dog()`
if(this !== namespace) {
return constructor.apply(this, arguments);
}
// static call: `Dog()`
else {
// we do no allow extending class `Dog`
return false;
}
};
})(global_namespace);
So now, we can do this:
var giraffe = new Animal('Mr. Giraffe', 720);
giraffe.speak(); // "Mr. Giraffe says nothing"
giraffe.weigh(); // "Mr. Giraffe weighs 720 lbs"
var buddy = new Dog('Buddy', 50);
buddy.speak(); // "Buddy says bark!"
buddy.weigh(); // "Buddy weighs 50 lbs"
// "Buddy has not been fed yet"
buddy.feed();
buddy.weigh(); // "Buddy weighs 55 lbs"
// "Buddy has been eating :)"
This allows private, protected and public fields/functions. Both protected and public field/functions may be overwritten and extended.
console.log(giraffe); // "{Animal}"
console.log(buddy); // "{Dog}"
I have been working on another interesting javascript project and implemented something that may be closer to what you are looking for.
Implement.js
Interested in you thoughts.
I have an api method that gets a lot of data in the application start up.
90% of the data is relevant for all application users and the other 10% need to be changed by the user id and his environment and app version.
To avoid calling the first method every time user connect and make the start up slower,
i added : AspNetCacheProfile attribute.
But in this situation i can`t use the user id, environment and version at this method
because it is the data of the first user called the method.
So,
I added new method (the second one) and set the AspNetCacheProfile attribute above it
and called this method from the first one.
This way i can cache the general data and update the other 10% each call.
I just wanted to know .. will it work ?
I was not sure because the second method is not called directly, it is called from the first one.
[WebGet(UriTemplate = "/GetData")]
public APIResponse GetData()
{
try
{
MyCachedResponse = GetMyCachedResponse();
foreach (var info in data.info)
{
if (Something)
{
// Update some specific values inside
}
}
AppState.CurrentResponse.Data = data;
}
return AppState.CurrentResponse;
}
[AspNetCacheProfile("OneMinuteCaching")]
private MyCachedResponse GetMyCachedResponse()
{
return new MyCachedResponse(categories);
}
So I have a number of different potential object that can output data (strings). What I want to be able to do, is to Run a generic Output.WriteLine function, with the potential arguments that define where you want it to be outputted to. What I've got for code -
//Defined in static class Const
public enum Out : int { Debug = 0x01, Main = 0x02, Code = 0x04 };
static class Output
{
private static List<object> RetrieveOutputMechanisms(Const.Out output)
{
List<object> result = new List<object>();
#if DEBUG
if (bitmask(output, Const.Out.Debug))
result.Add(1);//Console); //I want to add Console here, but its static
#endif
if (bitmask(output, Const.Out.Main))
if (Program.mainForm != null)
result.Add(Program.mainForm.Box);
if (bitmask(output, Const.Out.Code))
if (Program.code!= null)
result.Add(Program.code.Box);
return result;
}
public static void WriteLine(Color color, string str, Const.Out output = Const.Out.Debug & Const.Out.Main)
{
Console.WriteLine(
List<object> writers = RetrieveOutputMechanisms(output);
foreach (object writer in writers)
writer.WriteLine(str, color);
}
}
The point of this, is that the output destinations are not always existent, as they are on forms that may or may not exist when these calls are called. So the idea is to determine which ones you're trying to print to, determine if it exists, add it to the list of things to be printed to, then loop through and print to all of them if they implement the "WriteLine" method.
The two problems that I've come across, are
That Console is a static class, and can't properly (as far as my knowledge goes) be added to the object list.
I don't know how I can assert that the objects in the list define WriteLine, and cast them to something that would apply to more than one base Type. Assuming I can get Console to work properly in this scheme, that would be the obvious problem, its not of the same base type as the actual Boxes, but also, if I had something that wasnt a Box, then it would be lovely to do something like
foreach (object writer in writers)
.WriteLine(str, color)
so that I wouldn't have to individually cast them.
The bigger reason that I don't simply WriteLine from the RetrieveOutputMechanisms function, is that I want this to cover more than just WriteLine, which means that I would need to copy the bitmask code to each function.
EDIT: I realise that adding public properties to Program is a bad idea, if you know how I can avoid it (the necessity coming from needing to be able to access any WriteLine-able form objects that come and go, from anywhere), by all means please elaborate.
One way would be to use an Action (a delegate) and store those in your List. This will work for Console and any other class as you can easily write a lambda (or a 2.0 delegate) to map your output variables to the right parameters in the called method. There will be no need for casting. It could work something like this:
(This assumes you are using C# 3.5 or later but you can do all this in anything from 2.0 and on using delegates)
static class Output
{
private static List<Action<string, Color>> RetrieveOutputMechanisms(Const.Out output)
{
List<Action<string, Color>> result = new List<string, Color>();
#if DEBUG
if (bitmask(output, Const.Out.Debug))
result.Add((s, c) => Console.WriteLine(s, c)); //I want to add Console here, but its static
#endif
if (bitmask(output, Const.Out.Main))
if (Program.mainForm != null)
result.Add((s, c) => Program.mainForm.Box.WriteLine(s, c));
if (bitmask(output, Const.Out.Code))
if (Program.code!= null)
result.Add((s, c) => Program.code.Box.WriteLine(s, c));
return result;
}
public static void WriteLine(Color color, string str, Const.Out output = Const.Out.Debug & Const.Out.Main)
{
var writers = RetrieveOutputMechanisms(output);
foreach (var writer in writers)
writer(str, color);
}
}
(edit to add)
You could change this more significantly to allow classes to "register" to be able to do the writing for a specific "output mechanism" in the Output class itself. You could make Output a singleton (there are arguments against doing that but it would be better than sticking public static variables in your main program for this purpose). Here is an example with more significant changes to your original class:
public sealed class Output
{
private Dictionary<Out, Action<string, Color>> registeredWriters = new Dictionary<Out, Action<string, Color>>();
public static readonly Output Instance = new Output();
private void Output() { } // Empty private constructor so another instance cannot be created.
public void Unregister(Out outType)
{
if (registeredWriters.ContainsKey(outType))
registeredWriters.Remove(outType);
}
// Assumes caller will not combine the flags for outType here
public void Register(Out outType, Action<string, Color> writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
if (registeredWriters.ContainsKey(outType))
{
// You could throw an exception, such as InvalidOperationException if you don't want to
// allow a different writer assigned once one has already been.
registeredWriters[outType] = writer;
}
else
{
registeredWriters.Add(outType, writer);
}
}
public void WriteLine(Color color, string str, Const.Out output = Const.Out.Debug & Const.Out.Main)
{
bool includeDebug = false;
#if DEBUG
includeDebug = true;
#endif
foreach (var outType in registeredWriters.Keys)
{
if (outType == Const.Out.Debug && !includeDebug)
continue;
if (bitmask(output, outType))
registeredWriters[outType](str, color);
}
}
}
Then elsewhere in your program, such as in the form class, to register a writer, do:
Output.Instance.Register(Const.Out.Main, (s, c) => this.Box.WriteLine(s, c));
When your form is unloaded you can then do:
Output.Instance.Unregister(Const.Out.Main);
Then another way would be to not use a singleton. You could then have more than one Output instance for different purposes and then inject these into your other classes. For instance, change the constructor for your main form to accept an Output parameter and store this is an object variable for later use. The main form could then pass this on to a child form that also needs it.
If your objects that have data that need to be written behave like this:
A always writes to console and log
B always writes to log
C always writes to console
For all data, then your best bet would be to declare an interface and have each of them implement the interface method for output. Then, in your calling code, declare them not as their actual types but instead of type IOutput or whatever interface u call that has the method. Then have two helper methods, one for actually outputting to console and one for actually outputting to a log file. A would call both helpers, B and C their respective ones.
If, on the other hand, your objects will write to various logs at differing times:
A, B and C sometimes write to console and sometimes to log, depending on some property
Then I would recommend you create an event handler for when a class wants something to be written. Then, have the logic that discerns what writes to console and what writes to log in a listener class and attach the appropriate ones to that output event. That way, you can keep the logic about what is being written to where in classes that encapsulate just that functionality, while leaving the A, B and C classes free of dependencies that may come to bite you down the road. Consider having a monolithic method as you describe which uses a bitmask. As soon as the behavior of A, B or C's logging changes, or if you need to add a new output, you suddenly need to worry about one class or method affecting all of them at once. This makes it less maintainable, and also trickier to test for bugs.
MethodInfo methodname = typeof(object).GetMethod("MethodA");
Then just use a if statement to check if methodname is null or not.
Long story short
Say I have the following code:
// a class like this
class FirstObject {
public Object OneProperty {
get;
set;
}
// (other properties)
public Object OneMethod() {
// logic
}
}
// and another class with properties and methods names
// which are similar or exact the same if needed
class SecondObject {
public Object OneProperty {
get;
set;
}
// (other properties)
public Object OneMethod(String canHaveParameters) {
// logic
}
}
// the consuming code would be something like this
public static void main(String[] args) {
FirstObject myObject=new FirstObject();
// Use its properties and methods
Console.WriteLine("FirstObject.OneProperty value: "+myObject.OneProperty);
Console.WriteLine("FirstObject.OneMethod returned value: "+myObject.OneMethod());
// Now, for some reason, continue to use the
// same object but with another type
// -----> CHANGE FirstObject to SecondObject HERE <-----
// Continue to use properties and methods but
// this time calls were being made to SecondObject properties and Methods
Console.WriteLine("SecondObject.OneProperty value: "+myObject.OneProperty);
Console.WriteLine("SecondObject.OneMethod returned value: "+myObject.OneMethod(oneParameter));
}
Is it possible to change FirstObject type to SecondObject and continue to use it's properties and methods?
I've total control over FirstObject, but SecondObject is sealed and totally out of my scope!
May I achieve this through reflection? How? What do you think of the work that it might take to do it? Obviously both class can be a LOT more complex than the example above.
Both class can have templates like FirstObject<T> and SecondObject<T> which is intimidating me to use reflection for such a task!
Problem in reality
I've tried to state my problem the easier way for the sake of simplicity and to try to extract some knowledge to solve it but, by looking to the answers, it seems obvious to me that, to help me, you need to understand my real problem because changing object type is only the tip of the iceberg.
I'm developing a Workflow Definition API. The main objective is to have a API able to be reusable on top of any engine I might want to use(CLR through WF4, NetBPM, etc.).
By now I'm writing the middle layer to translate that API to WF4 to run workflows through the CLR.
What I've already accomplished
The API concept, at this stage, is somehow similar to WF4 with ActivityStates with In/Out Arguments and Data(Variables) running through the ActivityStates using their arguments.
Very simplified API in pseudo-code:
class Argument {
object Value;
}
class Data {
String Name;
Type ValueType;
object Value;
}
class ActivityState {
String DescriptiveName;
}
class MyIf: ActivityState {
InArgument Condition;
ActivityState Then;
ActivityState Else;
}
class MySequence: ActivityState {
Collection<Data> Data;
Collection<ActivityState> Activities;
}
My initial approach to translate this to WF4 was too run through the ActivitiesStates graph and do a somehow direct assignment of properties, using reflection where needed.
Again simplified pseudo-code, something like:
new Activities.If() {
DisplayName=myIf.DescriptiveName,
Condition=TranslateArgumentTo_WF4_Argument(myIf.Condition),
Then=TranslateActivityStateTo_WF4_Activity(myIf.Then),
Else=TranslateActivityStateTo_WF4_Activity(myIf.Else)
}
new Activities.Sequence() {
DisplayName=mySequence.DescriptiveName,
Variables=TranslateDataTo_WF4_Variables(mySequence.Variables),
Activities=TranslateActivitiesStatesTo_WF4_Activities(mySequence.Activities)
}
At the end of the translation I would have an executable System.Activities.Activity object. I've already accomplished this easily.
The big issue
A big issue with this approach appeared when I began the Data object to System.Activities.Variable translation. The problem is WF4 separates the workflow execution from the context. Because of that both Arguments and Variables are LocationReferences that must be accessed through var.Get(context) function for the engine to know where they are at runtime.
Something like this is easily accomplished using WF4:
Variable<string> var1=new Variable<string>("varname1", "string value");
Variable<int> var2=new Variable<int>("varname2", 123);
return new Sequence {
Name="Sequence Activity",
Variables=new Collection<Variable> { var1, var2 },
Activities=new Collection<Activity>(){
new Write() {
Name="WriteActivity1",
Text=new InArgument<string>(
context =>
String.Format("String value: {0}", var1.Get(context)))
},
new Write() {
//Name = "WriteActivity2",
Text=new InArgument<string>(
context =>
String.Format("Int value: {0}", var2.Get(context)))
}
}
};
but if I want to represent the same workflow through my API:
Data<string> var1=new Data<string>("varname1", "string value");
Data<int> var2=new Data<int>("varname2", 123);
return new Sequence() {
DescriptiveName="Sequence Activity",
Data=new Collection<Data> { var1, var2 },
Activities=new Collection<ActivityState>(){
new Write() {
DescriptiveName="WriteActivity1",
Text="String value: "+var1 // <-- BIG PROBLEM !!
},
new Write() {
DescriptiveName="WriteActivity2",
Text="Int value: "+Convert.ToInt32(var2) // ANOTHER BIG PROBLEM !!
}
}
};
I end up with a BIG PROBLEM when using Data objects as Variables. I really don't know how to allow the developer, using my API, to use Data objects wherever who wants(just like in WF4) and later translate that Data to System.Activities.Variable.
Solutions come to mind
If you now understand my problem, the FirstObject and SecondObject are the Data and System.Activities.Variable respectively. Like I said translate Data to Variable is just the tip of the iceberg because I might use Data.Get() in my code and don't know how to translate it to Variable.Get(context) while doing the translation.
Solutions that I've tried or thought of:
Solution 1
Instead of a direct translation of properties I would develop NativeActivites for each flow-control activity(If, Sequence, Switch, ...) and make use of CacheMetadata() function to specify Arguments and Variables. The problem remains because they are both accessed through var.Get(context).
Solution 2
Give my Data class its own Get() function. It would be only an abstract method, without logic inside that it would, somehow, translate to Get() function of System.Activities.Variable. Is this even possible using C#? Guess not! Another problem is that a Variable.Get() has one parameter.
Solution 3
The worst solution that I thought of was CIL-manipulation. Try to replace the code where Data/Argument is used with Variable/Argument code. This smells like a nightmare to me. I know next to nothing about System.reflection.Emit and even if I learn it my guess is that it would take ages ... and might not even be possible to do it.
Sorry if I ended up introducing a bigger problem but I'm really stuck here and desperately needing a tip/path to go on.
This is called "duck typing" (if it looks like a duck and quacks like a duck you can call methods on it as though it really were a duck). Declare myObject as dynamic instead of as a specific type and you should then be good to go.
EDIT: to be clear, this requires .NET 4.0
dynamic myObject = new FirstObject();
// do stuff
myObject = new SecondObject();
// do stuff again
Reflection isn't necessarily the right task for this. If SecondObject is out of your control, your best option is likely to just make an extension method that instantiates a new copy of it and copies across the data, property by property.
You could use reflection for the copying process, and work that way, but that is really a separate issue.