I am currently writing a program in C#, this program has a folder called Classes, many subfolders named a - f, and actual cs files within that folder named aa - cc.
a-f are namespaces
aa-cc are classes.
So if I wanted to invoke a method from Classes\b\bb.cs I'd have to type every time
b.bb,methodName();
It will also generate two Strings which will decide what we are going to be executing.
String myType = "b";
String myClass = "bb";
String toReturn = "";
There are many combinations of myType and myClass so I've had to write a lot of if loops
if (myType.equals("b") && myClass.equals("bb") return toReturn = b.bb.myMethod();
if (myType.equals("b") && myClass.equals("aa") return toReturn = b.aa.myMethod();
this is quite a lot of typing and I feel like there is an easier way to do this since I already know what know what namespace I want to access and what method I want to call.
Is there any way I could do something like
myType.myClass.myMethod()
where myType is the namespace, and myClass is the class I wish to call. This would avoid me typing out ever possible combination.
Improved sample with delegates. Homework: add hash to store delegates in GetDelegate method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using TestConsole.Data;
namespace NamespaceA
{
public class ClassAB
{
public void MyMethod()
{
Console.WriteLine("You invoke NamespaceA.ClassAB.MyMethod");
}
public static void MyStaticMethod()
{
Console.WriteLine("You invoke NamespaceA.ClassAB.MyStaticMethod");
}
}
}
namespace TestConsole
{
public delegate void DoSomethingUseful(); // same as Action delegate
class Program
{
/// <summary>
/// create delegate
/// </summary>
/// <param name="namespace"> namespace name </param>
/// <param name="class"> class name </param>
/// <param name="method"> method name </param>
/// <returns></returns>
public static DoSomethingUseful GetDelegate(string #namespace, string #class, string method)
{
// common argument checks
if (#namespace == null) throw new ArgumentNullException("namespace");
if (#class == null) throw new ArgumentNullException("class");
if (method == null) throw new ArgumentNullException("method");
// find class
Type type = Type.GetType(#namespace + "." + #class);
if (type == null) throw new Exception("type not found");
// find method
MethodInfo methodInfo = type.GetMethod(method);
if (methodInfo == null) throw new Exception("method not found");
// create the delegate
return (DoSomethingUseful)Delegate.CreateDelegate(typeof(DoSomethingUseful), methodInfo.IsStatic ? null : Activator.CreateInstance(type), methodInfo);
}
static void Main(string[] args)
{
// creating delegates
DoSomethingUseful methodA = GetDelegate("NamespaceA", "ClassAB", "MyMethod");
DoSomethingUseful methodB = GetDelegate("NamespaceA", "ClassAB", "MyStaticMethod");
// usage
methodA();
methodB();
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
Complete code sample below.
Remember, that you should create class instance, if your class method is not static (object instance = Activator.CreateInstance(type););
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestConsole.Data;
namespace NamespaceA
{
public class ClassAB
{
public void MyMethod()
{
Console.WriteLine("You invoke NamespaceA.ClassAB.MyMethod");
}
public static void MyStaticMethod()
{
Console.WriteLine("You invoke NamespaceA.ClassAB.MyStaticMethod");
}
}
}
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
Type type = Type.GetType("NamespaceA.ClassAB");
object instance = Activator.CreateInstance(type);
type.GetMethod("MyMethod").Invoke(instance, null); // instance is required
type.GetMethod("MyStaticMethod").Invoke(null, null); // instance is not required
Console.WriteLine();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
use static.
public static HelperClass
{
public static void HelperMethod() {
// ...
}
}
Usage (after adding a reference to your Class Library).
HelperClass.HelperMethod();
Related
Casting does not make copies of objects. More concretely IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle, reference equals is false if I change the log at the end from the Cast<BaseClass> to Cast<DerivedClass1>. Check logs at the main program.
are equal: True areEqualRef: True areEqualRef: False
Posting the code, just in case, omit it of you get my point playing around with the fiddle :)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp17
{
public class BaseClass {
string name = "I am base";
public Type type;
public enum Type {
a,b,c,d
}
public BaseClass(Type type) {
this.type = type;
}
}
public class DerivedClass1 : BaseClass
{
string name = "I am derivedA";
public DerivedClass1(): base(Type.a) {
}
}
public class DerivedClass2 : BaseClass
{
string name = "I am derivedB";
public DerivedClass2() : base(Type.b)
{
}
}
public class Foo
{
public Dictionary<BaseClass.Type, List<BaseClass>> dict = new Dictionary<BaseClass.Type, List<BaseClass>>();
public Foo() {
dict[BaseClass.Type.a] = new List<BaseClass>();
dict[BaseClass.Type.b] = new List<BaseClass>();
dict[BaseClass.Type.c] = new List<BaseClass>();
dict[BaseClass.Type.d] = new List<BaseClass>();
AddItem(new DerivedClass1());
AddItem(new DerivedClass1());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
}
public IEnumerable<T> GetEnumByType<T>(BaseClass.Type type) where T : BaseClass
{
if (dict.ContainsKey(type))
{
if (type == BaseClass.Type.a)
{
Console.WriteLine($"are equal: { object.ReferenceEquals(dict[type].Cast<T>(), dict[BaseClass.Type.a])}");
}
return dict[type].Cast<T>();
}
return null;
}
public void AddItem<T>(T item) where T : BaseClass
{
dict[item.type].Add(item);
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
IEnumerable myList = foo.GetEnumByType<BaseClass>(BaseClass.Type.a);
Console.WriteLine($"areEqualRef: {object.ReferenceEquals(foo.dict[BaseClass.Type.a].Cast<BaseClass>(), foo.dict[BaseClass.Type.a])}");
Console.ReadLine();
}
}
}
Update:
Updated the fiddle with both logs to avoid the need of copy/pasting
You need to notionally separate what is being compared here. When it says that Enumerable.Cast<T> doesn't make copies of objects, it is talking about the individual objects in the sequence. Not the sequence itself. In order to perform the necessary reshaping, the sequence returned from the Cast<T> method is a different wrapper/decorator instance over the original sequence.
Since you're using ReferenceEquals on the sequence, this will report false. However, if you were to compare each object from the sequences (pairwise in turn), you would find that those were the same objects.
i am using this code
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
new Program().DoTest();
}
public void DoTest()
{
var a = LoggingAdvice<asd>.Create(new a());
a.targetMethod("nadeem", 123, null);
}
}
public class LoggingAdvice<T> : DispatchProxy
{
private T _decorated;
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var result = targetMethod.Invoke(_decorated, args);
var resultTask = result as Task;
return result;
}
public static T Create(T decorated)
{
object proxy = Create<T, LoggingAdvice<T>>();
((LoggingAdvice<T>)proxy).SetParameters(decorated);
return (T)proxy;
}
private void SetParameters(T decorated)
{
if (decorated == null)
{
throw new ArgumentNullException(nameof(decorated));
}
_decorated = decorated;
}
}
public class asd
{
public asd()
{
}
public int targetMethod(string name, int number, int? count)
{
Console.WriteLine(name);
Console.WriteLine(number);
Console.WriteLine(count.HasValue ? count.Value.ToString() : "NULL");
return 1;
}
}
}
the most important thing about it, is this line of code
var result = targetMethod.Invoke(_decorated, args);
the target method has 3 parameters, one of them is nullable integer as the following
public int targetMethod(string name, int number, int? count)
the args that is getting passed to Invoke method has the following values as you can view it in the visual studio debugging mode:
["nadeem", 123, (null)]
the invoke is raising an exception that i cannot convert string to nullable integer.
how i can avoid this type of issue, note that i am not sure which function i am going to be invoked, i would only know it on runtime.
I was making a test case for some code on binary search tree my professor gave
public static void Main(string [] args)
{
//on my prof's code, public class BinSearchTree<T>
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
myTree.Insert(5);
myTree.Insert(2);
myTree.Insert(1);
Console.WriteLine(myTree.ToString());
Console.ReadKey();
}
It compiles, but it displays
BinSearchTree`1[System.Int32]
Can somebody tell me why it displays that?
my prof's code:
public class BinSearchTree<T> where T : IComparable<T>
{
private class OurTreeNode<T>
{
public T Data { get; set; }
public OurTreeNode<T> Left;
public OurTreeNode<T> Right;
public OurTreeNode(T d = default(T), OurTreeNode<T> leftnode = null, OurTreeNode<T> rightnode = null)
{
Data = d;
Left = leftnode;
Right = rightnode;
}
public override string ToString()
{
return Data.ToString();
}
}
//...other methods
//prof's Insert method
public void Insert(T newItem)
{
mRoot = Insert(newItem, mRoot);
}
private OurTreeNode<T> Insert(T newItem, OurTreeNode<T> pTmp)
{
if (pTmp == null)
return new OurTreeNode<T>(newItem, null, null);
else if (newItem.CompareTo(pTmp.Data) < 0)
pTmp.Left = Insert(newItem, pTmp.Left);
else if (newItem.CompareTo(pTmp.Data) > 0)
pTmp.Right = Insert(newItem, pTmp.Right);
else
throw new ApplicationException("...");
return pTmp;
}
}
I tried adding a ToString() method after the Insert method but it gives me an error when I used foreach. Is there a way of displaying it without making too much extra methods?
The class is using the default (Object's) ToString() implementation. You have 2 options:
walk though the elements of the tree and print it yourself
ask the author to implement/override the ToString() method
Can somebody tell me why it displays that?
It displays that because ToString() prints the type definition.
Default implementations of the Object.ToString method return the fully qualified name of the object's type. (from the docs)
For instance, the following short program prints System.Collections.Generic.List`1[System.Int32], which is the type of List<int>.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
List<int> myTree = new List<int>();
myTree.Add(10);
Console.WriteLine(myTree.ToString());
}
}
Here are the rudiments of how to override the ToString() method to produce some meaningful output.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
Console.WriteLine(myTree.ToString());
}
}
public class BinSearchTree<T> where T : IComparable<T>
{
private List<T> values = new List<T>();
// rest of class omitted for clarity
public void Insert(T val) {
values.Add(val);
}
public override string ToString() {
var result = string.Empty;
foreach(var v in values)
{
result += v + ", ";
}
return result;
}
}
Output
10, 15,
As you have created the object of BinaryTree Class and have not overridden the ToString() method inside BinaryTree Class. You have not created object of OurTreeNode class and not calling ToString() method overriden inside it. Hence it is giving you the default ToString() method output of BinaryTree Class.
BinSearchTree<int> myTree = new BinSearchTree<int>();
You are calling
Console.WriteLine(myTree.ToString());
This has been driving me mad for a while now. I have a class which contains other classes. I need to loop through the first class looking for typeof second class then retreive the value of the fields.
the below code obviously fails on the line
Console.WriteLine(field.GetValue(mFC.field.secondClassString));
as this isn't a valid field. Possibly I'm going about this the wrong way - any ideas?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
MyFirstClass mFC = new MyFirstClass();
FieldInfo[] fI = mFC.GetType().GetFields();
foreach (FieldInfo field in fI)
{
if (field.FieldType.Name == "MySecondClass")
{
//get the fields
Console.WriteLine(field.GetValue(mFC.field.secondClassString));
}
}
}
}
class MyFirstClass
{
public MySecondClass firstMSC = new MySecondClass("First Instance");
public MySecondClass secondMSC = new MySecondClass("Second Instance");
public string firstClassString = "I'm from the first class";
public int firstClassInt = 5;
}
class MySecondClass
{
public MySecondClass(string input)
{
this.secondClassString = input;
}
public string secondClassString;
public int secondClassInt = 10;
}
}
field.GetValue accepts the instance from which it gets the field value.
In your case I would expect it should be field.GetValue(mFC).
Also field.FieldType.Name == "MySecondClass" is not the best way to check the type as type name change will cause code to break. I recommend replacing it with field.FieldType == typeof(MySecondClass).
((MySecondClass)field.GetValue(mFC)).secondClassString;
use this inside console.writeline
I want to test whether the if-else statements are executed,
The "if" block returns the item from the dictionary/cache and returns the output, while "else" block adds the input inside the cache and returns an output
An interface of IModifyBehavior with a method Apply
I have this classes:
namespace Decorator
{
using System;
/// <summary>
/// Reverse Behavior
/// </summary>
public class ReverseBehavior : IModifyBehavior
{
/// <summary>
/// Applies the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>result</returns>
public string Apply(string value)
{
var result = string.Empty;
if (value != null)
{
char[] letters = value.ToCharArray();
Array.Reverse(letters);
result = new string(letters);
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// Caching Decorator
/// </summary>
public class CachingDecorator : IModifyBehavior
{
/// <summary>
/// The behavior
/// </summary>
private IModifyBehavior behavior;
public CachingDecorator(IModifyBehavior behavior)
{
if (behavior == null)
{
throw new ArgumentNullException("behavior");
}
this.behavior = behavior;
}
private static Dictionary<string, string> cache = new Dictionary<string, string>();
/// <summary>
/// Applies the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// value
/// </returns>
public string Apply(string value)
{
////Key = original value, Value = Reversed
var result = string.Empty;
//cache.Add("randel", "lednar");
if(cache.ContainsKey(value))
{
result = cache[value];
}
else
{
result = this.behavior.Apply(value);// = "reversed";
////Note:Add(key,value)
cache.Add(value, result);
}
return result;
}
}
}
Here's my current code for the test, the codes were able to passed the test, but I'm not sure if my implementation was correct:
[TestClass]
public class CachingDecoratorTest
{
private IModifyBehavior behavior;
[TestInitialize]
public void Setup()
{
this.behavior = new CachingDecorator(new ReverseBehavior());
}
[TestCleanup]
public void Teardown()
{
this.behavior = null;
}
[TestMethod]
public void Apply_Cached_ReturnsReversedCachedValue()
{
string actual = "randel";
////store it inside the cache
string cached = this.behavior.Apply(actual);
////call the function again, to test the else block statement
////Implement DRY principle next time
string expected = this.behavior.Apply(actual);
Assert.IsTrue(cached.Equals(expected));
}
[TestMethod]
public void Apply_NotCached_ReturnsReversed()
{
string actual = "randel";
string expected = "lednar";
Assert.AreEqual(expected, this.behavior.Apply(actual));
}
}
Sir/Ma'am your answers would be of great help. Thank you++
First of all I would actually test the two clases in isolation, as proper units.
Below I wrote up how I would test these. For this I'm using NUnit, and Moq (available in Nuget) as a mocking framework. But you can just change the test attributes and use MSTest instead.
For the reverse behavior I'm covering both a regular apply and applying to a null text:
using System;
using System.Linq;
using Decorator;
using NUnit.Framework;
namespace StackOverflow.Tests.HowToTest
{
[TestFixture]
public class ReverseBehaviorTest
{
[Test]
public void Apply()
{
const string someText = "someText";
var target = new ReverseBehavior();
var result = target.Apply(someText);
Assert.AreEqual(someText.Reverse(), result);
}
[Test]
public void Apply_WhenNull()
{
var target = new ReverseBehavior();
var result = target.Apply(null);
Assert.AreEqual(String.Empty, result);
}
}
}
And for the CachingDecorator, the constructor's exception throwing, applying with caching and without:
using System;
using Decorator;
using Moq;
using NUnit.Framework;
namespace StackOverflow.Tests.HowToTest
{
[TestFixture]
public class CachingDecoratorTest
{
[Test]
public void Constructor()
{
Assert.Throws(typeof(ArgumentNullException), () => new CachingDecorator(null));
}
[Test]
public void Apply_NotCached()
{
var internalBehaviorMock = new Mock<IModifyBehavior>();
internalBehaviorMock.Setup(x => x.Apply(It.IsAny<string>())).Returns<string>(y => y);
const string someText = "someText";
var target = new CachingDecorator(internalBehaviorMock.Object);
target.Apply(someText);
internalBehaviorMock.Verify(x => x.Apply(It.IsAny<string>()), Times.Once());
}
[Test]
public void Apply_Cached()
{
var internalBehaviorMock = new Mock<IModifyBehavior>();
internalBehaviorMock.Setup(x => x.Apply(It.IsAny<string>())).Returns<string>(y => y);
const string someOtherText = "someOtherText";
var target = new CachingDecorator(internalBehaviorMock.Object);
target.Apply(someOtherText);
target.Apply(someOtherText);
internalBehaviorMock.Verify(x => x.Apply(It.IsAny<string>()), Times.Once());
}
}
}
The best way would be to use a mocking framework (like Moq, for instance) to create a fake IModifyBehaviour object.
The Apply_NotCached_ReturnsReversed test would then verify that the Apply method of the mock object was called to generate the result. The Apply_Cached_ReturnsReversedCachedValue test would check that the result was returned without calling the Apply method of the mock object.
As it is, you test for the cached case doesn't actually prove that the result came from the cache.
just try to set cache dictionary values in your testcase and check for count after calling Apply(string value) method.
`
public void Apply_Cached_ReturnsReversedCachedValue()
{
Dictionary<string, string> cacheDict = new Dictionary<string, string>() { { "sometext", "txetemos" } };
string str = "sometext";
int dictionaryCountBeforeApply = cacheDict.Count();
//set value to static cache field using reflection, here dictionary count is 1
Type type = typeof(CachingDecorator);
FieldInfo cacheFieldInfo = type.GetField("cache", BindingFlags.NonPublic | BindingFlags.Static);
cacheFieldInfo.SetValue(decorator, cacheDict);
string result = decorator.Apply(str);
int dictionaryCountAfterApply = cacheDict.Count();
Assert.AreEqual(dictionaryCountAfterApply, dictionaryCountBeforeApply);
}
public void Apply_NotCached_ReturnsReversed()
{
Dictionary<string, string> cacheDict = new Dictionary<string, string>() { };
string str = "sometext";
int dictionaryCountBeforeApply = cacheDict.Count();
//set value to static cache field using reflection, here dictionary count is 0
Type type = typeof(CachingDecorator);
FieldInfo cacheFieldInfo = type.GetField("cache", BindingFlags.NonPublic | BindingFlags.Static);
cacheFieldInfo.SetValue(decorator, cacheDict);
string result = decorator.Apply(str);
int dictionaryCountAfterApply = cacheDict.Count();
Assert.AreNotEqual(dictionaryCountAfterApply, dictionaryCountBeforeApply);
}`