I have 4 methods which have similar code
private void LogExceptions(ObjA.Input input, int customerId)
{
//ObjA is a big object, thats why I try not to send the whole object in this method
Log(input);
Log(ObjA.Exceptions);
}
private void LogExceptions(ObjB.Input input, int customerId)
{
//ObjB is a big object, thats why I try not to send the whole object in this method
Log(input);
Log(ObjB.Exceptions);
}
and so on
I am not able to make it a template method such as
private void LogExceptions<T1,T2>(T1 input, int customerId) whereas T1:ObjA.Input,ObjB.Input
{
Log(T1);
Log(T2);
}
How to do it or is there any other way ?
Any help is appreciated in advance .
I don't think my question was helping get proper answers....
Here is the exact code....
private void LogExceptions(AccARef.Response response)
{
StringBuilder sbErrors = null;
if (response.ValMethod != null && response.ValMethod.IsValid == false)
{
if (response.ValMethod.Errors.Count() > 0)
{
sbErrors = new StringBuilder();
foreach (AccARef.Exception exp in response.ValMethod.Errors)
{
sbErrors.Append(" * " + exp.Message + exp.StackTrace + " ");
Console.WriteLine(strError.ToString())
}
}
}
}
private void LogExceptions(AccBRef.Response response)
{
StringBuilder sbErrors = null;
if (response.ValMethod != null && response.ValMethod.IsValid == false)
{
if (response.ValMethod.Errors.Count() > 0)
{
sbErrors = new StringBuilder();
foreach (AccBRef.Exception exp in response.ValMethod.Errors)
{
sbErrors.Append(" * " + exp.Message + exp.StackTrace + " ");
Console.WriteLine(strError.ToString())
}
}
}
}
Now AcctBRef and AcctARef cannot implement a common interface as they are not my objects. Or if they are no my objects, can I still decorate them to be mine ?
You don't even need generics in this case, if ObjA and ObjB either inherit from the same base blass or interface.
If you have
interface IBaseClass
{
IEnumerable<Something> Exceptions {get;set;}
InputType Input {get;set;}
}
class A : IBaseClass {}
class B : IBaseClass {}
You can just use this for your LogExceptions signature:
void LogExceptions(IBaseClass obj, int CustomerId)
{
Log(obj.Exceptions);
Log(obj.Input);
}
If they don't inherit from a common interface, then I suggest they should.
You cannot pass Type parameter to Log method. You have to pass an instance of Type parameter.
try following:
private void LogExceptions<T1, T2>(T1 input, T2 exceptions, int customerId)
{
Log(input);
Log(exceptions);
}
What I feel is if there are 4 methods and they don't have same method signature its completely fine, it doesn't always have to be generic it has to be readable as well.
Why would you make 4 calls Log(T1),Log(T2),Log(T3),Log(T4) if all you have to do is Log(OneofTheTypeWhichYouKnowWhenCallingTheMethod).
Having said that you can always have reflection to play around like in your case.
Related
Say I have some external classes that have methods sharing a signature by convention, but that do not implement an interface:
class A {
public string getError();
}
class B {
public string getError();
}
If I want to create a utility function that accepts objects of either type, I could use dynamic:
void printError(dynamic obj) {
Console.WriteLine("Error: {0}", obj.getError());
}
But if I passed a some class C without a getError method, this would be a runtime error. Given that I can't modify A or B (directly), is there a way to implement this so that it would be a compile-time error to pass a type without a getError method, similar to what we'd get with C++ templates?
It sounds like you have an XY Problem. Instead of figuring out how to make your code less type safe, why not just use a overloads and refactor?
public void PrintError(A obj)
{
Console.WriteLine("Error: {0}", obj.getError());
//maybe some more logic
}
public void PrintError(B obj)
{
Console.WriteLine("Error: {0}", obj.getError());
//maybe some more logic
}
The above code solves your problem, but its no longer DRY. This is where we refactor:
public void PrintError(A obj)
{
PrintError(obj.getError());
}
public void PrintError(B obj)
{
PrintError(obj.getError());
}
//This is private, so you can only call PrintError publicly with an A or B instance
private void PrintError(string error)
{
Console.WriteLine("Error: {0}", error);
//maybe some more logic
}
Now you have type safety, you aren't repeating yourself and you are not "fighting the language" by using it in a way counter to how it was designed.
Use more than one prototype
You can of course define more than one prototype, where each prototype accepts a different class. The compiler will automatically pick the method signature that matches. Example:
public static void PrintError(ExternalClasses.A a)
{
Console.WriteLine(a.getError());
}
public static void PrintError(ExternalClasses.B b)
{
Console.WriteLine(b.getError());
}
Use a single prototype, but with implicit conversion
Another approach would be to define your own class and set up implicit conversion:
public class ErrorContainer
{
protected string _error = null;
public string getError()
{
return _error;
}
public override string ToString()
{
return getError();
}
static public implicit operator ErrorContainer(ExternalClasses.A a)
{
var e = new ErrorContainer();
e._error = a.getError();
return e;
}
static public implicit operator ErrorContainer(ExternalClasses.B b)
{
var e = new ErrorContainer();
e._error = b.getError();
return e;
}
}
Then you can define PrintError to accept an ErrorContainer:
public static void PrintError(ErrorContainer e)
{
Console.WriteLine(e);
}
...which allows you to "pass" either type:
var a = new ExternalClasses.A();
PrintError(a);
var b = new ExternalClasses.B();
PrintError(b);
Under the covers, of course, both A and B are converted to an ErrorContainer.
Example on DotNetFiddle
This was from my university C# - windows forms exam, im trying to resolve some old subjects, but i seem to find myself stuck in this situation. This is my code:
abstract class CarFile
{
private string marca;
private readonly string serie;
public CarFile(string marca, string serie)
{
this.marca = marca;
this.serie = serie;
}
public string GetMarca
{
get { return this.marca; }
set { this.marca = value; }
}
public string GetSerie
{
get { return this.serie; }
}
public abstract string GetDescriere();
}
Then I have to do this:
my second class called ServiceFile : CarFile, ICloneable. in this class i have an array or list of strings called RepairComands which contains the necessary repairs.
- a private atribute called "motor" which can only take the following vallues {gas,gpl,hibrid} .
- a constructor which throws a generic exception if "serie==null"
-overrides the abrstract method getDescriere() to return the complete description of the car file
this is my code:
public class MyException : System.Exception
{
public MyException(string mesaj) : base(mesaj) { }
}
class ServiceFile : CarFile, ICloneable, IComparable, IReparabil
{
string[] RepairComands;
private enum motor { motorina, benzina, GPL, electric, hibrid };
public ServiceFile(string serie, string marca, string[] RepairComands):base(serie,marca){
if (serie == null)
{
throw new MyException("MESAJ");
}
this.RepairComands = RepairComands;
}
//not sure if this is correct
public override string GetDescriere()
{
string msj = string.Format("the car {0} with serial {1} and necess. repairs {2}", this.GetMarca, this.GetSerie, this.RepairComands);
return msj;
}
public object Clone()
{
ServiceFile clone = new ServiceFile(this.GetSerie, this.GetMarca, this.RepairComands);
return clone;
}
//implemented IComparable to be able to compare here 2 files by the number of repairs needed
public int CompareTo(object obj)
{
ServiceFile altafisa = (ServiceFile)obj;
if (this.RepairComands != altafisa.RepairComands)
return 1;
else return 0;
}
//overloads ToString to return the complete file description
public override string ToString()
{
return this.GetMarca + " "+ this.GetSerie + " " + this.RepairComands;
}
}
}
so far so good. this actually works.
but my problem comes now:
I have to define the interface IRep which contains 2 methods : void RepairCar() and void AddRepair(string repair).
THen ServiceFile class implements : IRep, and the function RepairCar() will be used for removing the last repair from the collection RepairComands
and the function AddRepair(string repair) will be used to add a repair in the collection RepairComands.
(For allowing the access to the private list of Repairs we should overload the index operator[] )
Thank you so much for your help, I'm a beginnes in C# and just wanted to understand better this subject that was given in my class so i could learn
Thank you
I want to inherit from NHibernate's SqlClientBatchingBatcher class exactly like this (code taken from TooManyRowsAffectedException with encrypted triggers):
public class NonBatchingBatcherWithoutVerification : SqlClientBatchingBatcher
{
public NonBatchingBatcherWithoutVerification(ConnectionManager connectionManager, IInterceptor interceptor) : base(connectionManager, interceptor)
{}
protected override void DoExecuteBatch(IDbCommand ps)
{
log.DebugFormat("Executing batch");
CheckReaders();
Prepare(currentBatch.BatchCommand);
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
{
Factory.Settings.SqlStatementLogger.LogBatchCommand(currentBatchCommandsLog.ToString());
currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
int rowsAffected = currentBatch.ExecuteNonQuery();
// Removed the following line
//Expectations.VerifyOutcomeBatched(totalExpectedRowsAffected, rowsAffected);
currentBatch.Dispose();
totalExpectedRowsAffected = 0;
currentBatch = new SqlClientSqlCommandSet();
}
}
Just notice some of the members accessed in the method here (like currentBatch or totalExpectedRowsAffected).
Well, it turns out these members are actually private in the superclass of the current NHibernate 3.3 source. So how do I effectively inherit the class without copying the whole thing? This is the unmodified NHibernate code of the class by the way:
public class SqlClientBatchingBatcher : AbstractBatcher
{
private int _batchSize;
private int _totalExpectedRowsAffected;
private SqlClientSqlCommandSet _currentBatch;
private StringBuilder _currentBatchCommandsLog;
private readonly int _defaultTimeout;
public SqlClientBatchingBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
: base(connectionManager, interceptor)
{
_batchSize = Factory.Settings.AdoBatchSize;
_defaultTimeout = PropertiesHelper.GetInt32(Cfg.Environment.CommandTimeout, Cfg.Environment.Properties, -1);
_currentBatch = CreateConfiguredBatch();
//we always create this, because we need to deal with a scenario in which
//the user change the logging configuration at runtime. Trying to put this
//behind an if(log.IsDebugEnabled) will cause a null reference exception
//at that point.
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
public override int BatchSize
{
get { return _batchSize; }
set { _batchSize = value; }
}
protected override int CountOfStatementsInCurrentBatch
{
get { return _currentBatch.CountOfCommands; }
}
public override void AddToBatch(IExpectation expectation)
{
_totalExpectedRowsAffected += expectation.ExpectedRowCount;
IDbCommand batchUpdate = CurrentCommand;
Driver.AdjustCommand(batchUpdate);
string lineWithParameters = null;
var sqlStatementLogger = Factory.Settings.SqlStatementLogger;
if (sqlStatementLogger.IsDebugEnabled || Log.IsDebugEnabled)
{
lineWithParameters = sqlStatementLogger.GetCommandLineWithParameters(batchUpdate);
var formatStyle = sqlStatementLogger.DetermineActualStyle(FormatStyle.Basic);
lineWithParameters = formatStyle.Formatter.Format(lineWithParameters);
_currentBatchCommandsLog.Append("command ")
.Append(_currentBatch.CountOfCommands)
.Append(":")
.AppendLine(lineWithParameters);
}
if (Log.IsDebugEnabled)
{
Log.Debug("Adding to batch:" + lineWithParameters);
}
_currentBatch.Append((System.Data.SqlClient.SqlCommand) batchUpdate);
if (_currentBatch.CountOfCommands >= _batchSize)
{
ExecuteBatchWithTiming(batchUpdate);
}
}
protected override void DoExecuteBatch(IDbCommand ps)
{
Log.DebugFormat("Executing batch");
CheckReaders();
Prepare(_currentBatch.BatchCommand);
if (Factory.Settings.SqlStatementLogger.IsDebugEnabled)
{
Factory.Settings.SqlStatementLogger.LogBatchCommand(_currentBatchCommandsLog.ToString());
_currentBatchCommandsLog = new StringBuilder().AppendLine("Batch commands:");
}
int rowsAffected;
try
{
rowsAffected = _currentBatch.ExecuteNonQuery();
}
catch (DbException e)
{
throw ADOExceptionHelper.Convert(Factory.SQLExceptionConverter, e, "could not execute batch command.");
}
Expectations.VerifyOutcomeBatched(_totalExpectedRowsAffected, rowsAffected);
_currentBatch.Dispose();
_totalExpectedRowsAffected = 0;
_currentBatch = CreateConfiguredBatch();
}
private SqlClientSqlCommandSet CreateConfiguredBatch()
{
var result = new SqlClientSqlCommandSet();
if (_defaultTimeout > 0)
{
try
{
result.CommandTimeout = _defaultTimeout;
}
catch (Exception e)
{
if (Log.IsWarnEnabled)
{
Log.Warn(e.ToString());
}
}
}
return result;
}
}
Did I overlook something? Seems to a rather bad approach to copy the whole thing just to override all access to any private members. I just want to override one method!
There is only one way to legally access private members of your base class: put the derived class inside the base class:
class Base
{
private int x;
private class Derived : Base
{
private void M()
{
Console.WriteLine(this.x); // legal!
}
}
}
Of course, if you could put the class inside the base class then you could also rewrite the base class so that the members were protected.
That the original author made the members private is a hint to you that the class was not designed for you to muck around with that data.
If they're set as private, there's really nothing (short of using Reflection, which is ugly and certainly not always safe) that you can do.
Private members of a superclass cannot be accessed, bcause they are private. Encapsulation in OOP is there to prohibit this direct access and so ensure that objects function properly.
There might be properties to access the private members, These are the ones you can use to read from/write to private members. The properties will ensure that no harm to the object will be done.
You can access private fields, properties and methods of a parent class using reflection (for example, accessing a field as described here: Reflecting a private field from a base class)
This is not safe, however as the idea of private is that the library implementation could change and those private methods, fields and properties could change or disappear. If they change the implementation, an update could break your code.
That said, I've done it a few times myself. You just need to weigh the risk.
Let me try to simplify my question:
I have four classes: Admins, Users, Players, Roles
The database returns names of methods that I will need to execute. For example if Admins_GetName is returned then GetName() method will need to be executed on the Admins class.
If Players_GetRank is returned then GetRank() method will need to be called on the Players class.
I don't want to write a huge IF or SWITCH statement with all my business logic in it. What would be the most efficient solution WITHOUT using reflection ? If possibly I would like to avoid the performance hit that reflection brings.
Keep in mind that all methods may have different parameters and but will return strings.
Here is what I'm thinking to do now:
1) Have a method with a switch statement that will break apart the database value and find the class and method I need to execute.
Something like:
switch(DbValue)
{
case DbValue == "Admins_GetName":
Declare a delegate to Admins.GetName();
return;
case: DbValue = "Players_GetRank"
Declare a delegate to Players.GetRank();
return;
.
.
.
etc
}
return class/method reference;
2) Pass the declaration from above to:
var myValue = Retrieved method.invoke()
Can you guys suggest me with the best way to accomplish this or help me out with the correct syntax on my idea of how to implement it.
Thank you.
Needs a little more context; for example, do all the methods in question have the same signature? In the general case, reflection is the most appropriate tool for this, and as long as you aren't calling it in a tight loop, it will be fine.
Otherwise, the switch statement approach is reasonable, but has the maintenance overhead. If that is problematic, I would be tempted to build a delegate cache at runtime, for example:
using System;
using System.Collections.Generic;
public class Program
{
public string Bar { get; set; }
static void Main()
{
var foo = new Foo();
FooUtils.Execute(foo, "B");
FooUtils.Execute(foo, "D");
}
}
static class FooUtils
{
public static void Execute(Foo foo, string methodName)
{
methodCache[methodName](foo);
}
static readonly Dictionary<string, Action<Foo>> methodCache;
static FooUtils()
{
methodCache = new Dictionary<string, Action<Foo>>();
foreach (var method in typeof(Foo).GetMethods())
{
if (!method.IsStatic && method.ReturnType == typeof(void)
&& method.GetParameters().Length == 0)
{
methodCache.Add(method.Name, (Action<Foo>)
Delegate.CreateDelegate(typeof(Action<Foo>), method));
}
}
}
}
public class Foo
{
public void A() { Console.WriteLine("A"); }
public void B() { Console.WriteLine("B"); }
public void C() { Console.WriteLine("C"); }
public void D() { Console.WriteLine("D"); }
public string Ignored(int a) { return ""; }
}
That approach can be extended to multiple target types by using generics:
static class FooUtils
{
public static void Execute<T>(T target, string methodName)
{
MethodCache<T>.Execute(target, methodName);
}
static class MethodCache<T>
{
public static void Execute(T target, string methodName)
{
methodCache[methodName](target);
}
static readonly Dictionary<string, Action<T>> methodCache;
static MethodCache()
{
methodCache = new Dictionary<string, Action<T>>();
foreach (var method in typeof(T).GetMethods())
{
if (!method.IsStatic && method.ReturnType == typeof(void)
&& method.GetParameters().Length == 0)
{
methodCache.Add(method.Name, (Action<T>)
Delegate.CreateDelegate(typeof(Action<T>), method));
}
}
}
}
}
I was tackled by this issue for too many times so i decided to share and see what you guys think, lets look at the following (dumb) exemple:
public delegate void ToRun();
class Runner {
ToRun tr;
public Runner(ToRun f) {
tr=f;
}
public void run() {
tr();
}
}
class CountingRunner : Runner {
ToRun tr;
int i;
public CountingRunner(ToRun f) : base(f+=inc) {
i=0;
}
private static void inc() {
i++; //COMPILATION ERROR - i is not (and logically cannot be) static!
}
}
well, what i want to ask is:
Q1: why do base() parms have to be static?
Q2: what if, as in my exemple, we want to combine nonstatic fields or methods with the call to the base constructor? what is the most OOP way to do that?
Note : try not to give bandaid solutions like "just dont use the base c'tor", cause there might be more complex situation where using base is unavoidable, so im looking for a reasonable well designed solution for this.
Thanks!
Update:
my exemple was too easy to crack,therefore i feel like i havent learned enough, so lets try to give another (pretty dumb still) exemple:
public delegate int HashFunc<E>(E e);
public interface HashTable<E> {
void insert(E e);
bool isMember(E e);
}
class HashArray<E> : HashTable<E> where E : IComparable<E> {
private E[] a;
private bool[] taken;
public readonly int n;
public int size {
get { return n; }
}
HashFunc<E> hash;
public HashArray(int m , HashFunc<E> hash ) {
n=2*m;
a=new E[n];
taken=new bool[n];
for (int i=0 ; i<n ; i++) taken[i]=false;
this.hash=hash;
}
public void insert(E e) {
int index=hash(e),i;
for (i=index ; i<n && taken[i]!=false ; ++i) ;
if (i>=n)
for (i=0 ; i<index && taken[i]!=false ; ++i) ;
if (i>=index) return;
taken[i]=true;
a[i]=e;
}
public bool isMember(E e) {
int i=hash(e);
for ( ; i<n && taken[i]!=false && a[i].CompareTo(e)!=0 ; ++i );
if (i>=n || taken[i]==false) return false;
return true;
}
}
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n,HashFunc) {
}
public static int HashFunc(int i) {
return (i%n);// n is a non static field, every hash table has its own size!
}
}
in this exemple we are giving some weird implementation for an hash table where the hash function is unknown, and a special class for hash table of ints with predefined hash function, notice that here again we need to combine the non static size of the hashtable n and base c'tor...
Q1: why do base() parms have to be static?
They must be static because the instance hasn't been defined at the time of the constructor call (that definition was "in progress").
Q2: what if, as in my exemple, we want to combine nonstatic fields or methods with the call to the base constructor? what is the most OOP way to do that?
To OOP-way would is just simple method overrides.
class Runner
{
ToRun tr;
public Runner(ToRun f)
{
tr=f;
}
public virtual void Run()
{
tr();
}
}
class CountingRunner : Runner {
int i;
public CountingRunner(ToRun f) : base(f) {
i=0;
}
public override void Run() {
i++;
base.Run();
}
}
This is what you want:
class Runner {
protected event Action _toRun;
public Runner() {
}
public void Run() {
var r = _toRun;
if (r != null)
_toRun();
}
}
class CountingRunner : Runner {
int i;
public CountingRunner(Action f) : base() {
_toRun += f;
}
public void inc() {
i++;
}
}
EDIT
For your particular example with hash tables, this problem is solved by the design of the language. Just call GetHashCode() on the elements of your hashtable to determine their hashcode. You don't need implementations to pass a hashing function.
To answer your more general question of "How should I send functions manipulating instance data to the base class," you should either capture your instance variables in a lambda expression and send that to the base class, or consider a design in which the base class doesn't need access to the instance functions of its derived classes. I would go with the latter :)
One such design would be to have the function a pure virtual call in the base class. That would require derived classes to implement the virtual call in order to be instantiated. So here you would have a abstract int GetHashCode(E item) function in the base class, and just override it in your subclasses. Again, in this specific case the language does this for you with the virtual GetHashCode() function defined for all types.
Here is a non-abstract example (derived classes aren't required to override the hashing function).
class HashArray<E> : HashTable<E> where E : IComparable<E> {
private E[] a;
private bool[] taken;
public readonly int n;
public int size {
get { return n; }
}
public HashArray(int m) {
n=2*m;
a=new E[n];
taken=new bool[n];
for (int i=0 ; i<n ; i++) taken[i]=false;
}
public void insert(E e) {
int index= GetSpecialHashCode(e)%n;
int i;
for (i=index ; i<n && taken[i]!=false ; ++i) ;
if (i>=n)
for (i=0 ; i<index && taken[i]!=false ; ++i) ;
if (i>=index) return;
taken[i]=true;
a[i]=e;
}
public bool isMember(E e) {
int i= GetSpecialHashCode(e)%n;
for ( ; i<n && taken[i]!=false && a[i].CompareTo(e)!=0 ; ++i );
if (i>=n || taken[i]==false) return false;
return true;
}
protected virtual int GetSpecialHashCode(E item) {
return item.GetHashCode();
}
}
So you get a default hashcode generating function, but derived classes are also welcome to supply their own.
Regarding both Q1 and Q2, it's not that the parameters must be static, but rather the parameters must be accessible at the time they are invoked.
And base constructors are invoked prior to the local constructor, which is why you can't use this members as parameter for example, and why you shouldn't invoke virtual calls.
Not totally sure what the ultimate goal of that would be, but it does resemble a Decorator pattern.
For your last example, I think this could work:
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n,i => HashFunc(i,n)) {
}
private static int HashFunc(int i, int n) {
return (i%n);// n is a non static field, every hash table has its own size!
}
}
If not, you can do this:
class HashFuncProvider {
private int n;
public HashFuncProvider(int n){
this.n = n;
}
public int HashFunc(int i) {
return (i%n);
}
}
class HashArrayInt : HashArray<int> {
public HashArrayInt(int n) : base (n, new HashFuncProvider(n).HashFunc) {
}
}