I have a piece of code that gets a specific portion of the namespace from the calling assembly. Now I want to unit test this code.
Is there a way to fake the name of the calling namespace using NUnit without implementing the NUnit testcase in that particular namespace?
Here is the method I want to test:
public static string FindCallingNameSpace()
{
var stackTrace = new StackTrace();
var stackFrames = stackTrace.GetFrames();
if (stackFrames != null)
{
int nrFrames = stackFrames.Length;
for (int i = 0; i < nrFrames; i++)
{
var methodBase = stackTrace.GetFrame(i).GetMethod();
var Class = methodBase.ReflectedType;
if (Class != null && Class.Namespace != null && Class.Namespace != "Foo.Common.WebService")
{
var Namespace = Class.Namespace.Split('.');
return Namespace[1];
}
}
}
throw new Exception("Can't determine calling namespace! Need this to determine correct api url to call!");
}
An example would be:
Bar.ExampleNs.SomeMethod() calls Foo.Common.WebService.CallApi() which itself calls the method above to retrieve the namespace from SomeMethod(). The result then would be "ExampleNs".
Now is it possible to create an NUnit UnitTest that is coded in the namespace MyUnitTests.ApiTest.TestNameSpace() but inside Foo.Common.WebService the call appears to come from Bar.ExampleNs.SomeMethod() so I can test for "ExampleNs"?
I think by far the simplest way of achieving what you're after is to just create a call forwarder and call the FindCallingNamespace method via the forwarder. So, assuming that the FindCallingNamespace method is in a class CallerStuff you create this:
namespace SomeNameSpace.ToTest {
static class RemoteCaller {
static public string Run() {
return CallerStuff.FindCallingNameSpace();
}
}
}
Then in your test you call RemoteCaller.Run, rather than CallerStuff.FindCallingNamespace.
However, you mentioned having Parameterized Tests, so presumably you might end up with a few different namespaces you want to test from which would mean more remote callers in different namespaces, which got me thinking that there might be a more generic approach.
The code below, essentially creates these wrapper classes for you by compiling them on the fly and then invoking them.
class CodeMaker {
static string _codesectionOne = #"
using Foo.Common.WebService;
namespace ";
static string _codesectionTwo = #" {
class RemoteCaller {
static public string Run() {
return CallerStuff.FindCallingNameSpace();
}
}
}";
public static string CompileAndCall(string targetNamespace,
string referenceAssembly) {
CompilerParameters CompilerParams = new CompilerParameters();
string outputDirectory = Directory.GetCurrentDirectory();
CompilerParams.GenerateInMemory = true;
CompilerParams.TreatWarningsAsErrors = false;
CompilerParams.GenerateExecutable = false;
CompilerParams.CompilerOptions = "/optimize";
string[] references = { "System.dll", referenceAssembly};
CompilerParams.ReferencedAssemblies.AddRange(references);
CSharpCodeProvider provider = new CSharpCodeProvider();
var codeToCompile = _codesectionOne + targetNamespace + _codesectionTwo;
CompilerResults compile = provider.CompileAssemblyFromSource(CompilerParams,
codeToCompile);
if (compile.Errors.HasErrors) {
string text = "Compile error: ";
foreach (CompilerError ce in compile.Errors) {
text += "rn" + ce.ToString();
}
throw new Exception(text);
}
Module module = compile.CompiledAssembly.GetModules()[0];
Type mt = null;
MethodInfo methInfo = null;
if (module != null) {
mt = module.GetType(targetNamespace + ".RemoteCaller");
}
if (mt != null) {
methInfo = mt.GetMethod("Run");
}
if (methInfo != null) {
return (string)methInfo.Invoke(null, null);
}
throw new InvalidOperationException("It's all gone wrong!");
}
}
You would then invoke the method from your test:
Assert.AreEqual("Fiddle", CodeMaker.CompileAndCall("Wibble.Fiddle.Con", "SO.dll"));
Assert.AreEqual("Fuddle", CodeMaker.CompileAndCall("Wibble.Fuddle.Con", "SO.dll"));
Note, "SO.dll" in the example above is the name of the assembly containing the CallerStuff.FindCallingNamespace
Using the compiler to generate the caller classes is probably overkill for what you're after and you might have to tweak the error handling in the code if you do decide to use it. If you're invoking the generated classes multiple times from different tests, then it may also be worth caching them, possibly through a dictionary keyed off namespace rather than compiling them every time. Compile + Call code is based on this blog post by Simeon Pilgrim.
Related
I have a C# app that exports to Excel using ClosedXML. It works fine but just ran into an issue where when i hit the :
var ms = new MemoryStream();
workbook.SaveAs(ms);
I get an exception:
' ', hexadecimal value 0x0B, is an invalid character
Its definitely data related because it I look at certain data it works fine but other data it causes this issue.
how can i figure out which character is causing the issue? Also, once I figure that out, what is the best way of finding where this character is within my data?
Since you have invalid characters in the data / strings you put into the ClosedXML sheet, you have to find them and get them out.
The simplest solution is to add
.Replace((0x0B).ToString(), " ")
to all your strings to get rid of the vertical tabs and replace them with spaces.
Since ClosedXML is an open source project, the simplest way of tracking the error down would be building it from the source *, and then running your code against the library in debug mode.
Once you see the full stack trace, you should be able to identify the spot from which the error is coming. Good chances are that it is a bug in the way the ClosedXML project uses Microsoft XML libraries, because the error that you mentioned is reported by a library outside the ClosedXML project.
* I downloaded the project, and tried building it. Everything in the closedxml-79843.zip package builds correctly.
Since ClosedXML doesn't prevent you from using the 0x0B character in values, you'll either have to scrub your data of it yourself (as suggested by #Raidri), or you could force and exception, or do a string replace when the value is set. I've created a sample program below which uses Castle's Dynamic Proxy to wrap the IXLWorksheet and IXLCell interfaces. Firstly, we proxy the IXLWorksheet values (which returned from adding a new worksheet as in the example below, or by indexing an existing worksheet). This needs to be done manually via a method call; everything else from then on is set up. When accessing cells (via the Cell methods, or the ActiveCell property) a proxied IXLCell value is returned which checks the data being set via the Value property and the SetValue method. The check is done in the ValidateMethodInterceptor as per the comments. This whole mechanism can be left in your codebase and turned on/off via a switch in the Program.Proxy method if you so desire.
As a further alternative, the package EPPlus (which has similar functionality to ClosedXML) doesn't crash when confronted with the VT character. Instead it replaces it with the value _x00B_. Perhaps a switch would be more beneficial?
internal class Program
{
private static void Main(string[] args)
{
var stream = new MemoryStream();
using (stream)
{
using (var workbook = new XLWorkbook())
{
using (var worksheet = Proxy(workbook.Worksheets.Add("Sheet 1")))
{
worksheet.Cell("A1").Value = "This is a test";
worksheet.Cell("A2").Value = "This \v is a test";
workbook.SaveAs(stream);
}
}
}
}
public static IXLWorksheet Proxy(IXLWorksheet target)
{
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions { Selector = new WorksheetInterceptorSelector() };
return generator.CreateInterfaceProxyWithTarget<IXLWorksheet>(target, options);
}
}
public class WorksheetInterceptorSelector : IInterceptorSelector
{
private static readonly MethodInfo[] methodsToAdjust;
private readonly ProxyCellInterceptor proxyCellInterceptor = new ProxyCellInterceptor();
static WorksheetInterceptorSelector()
{
methodsToAdjust = typeof(IXLWorksheet).GetMethods()
.Where(x => x.Name == "Cell")
.Union(new[] { typeof(IXLWorksheet).GetProperty("ActiveCell").GetGetMethod() })
.ToArray();
}
#region IInterceptorSelector Members
public IInterceptor[] SelectInterceptors(System.Type type, System.Reflection.MethodInfo method, IInterceptor[] interceptors)
{
if (!methodsToAdjust.Contains(method))
return interceptors;
return new IInterceptor[] { proxyCellInterceptor }.Union(interceptors).ToArray();
}
#endregion
}
public class CellInterceptorSelector : IInterceptorSelector
{
private static readonly MethodInfo[] methodsToAdjust = new[] { typeof(IXLCell).GetMethod("SetValue"), typeof(IXLCell).GetProperty("Value").GetSetMethod() };
private ValidateMethodInterceptor proxyCellInterceptor = new ValidateMethodInterceptor();
#region IInterceptorSelector Members
public IInterceptor[] SelectInterceptors(System.Type type, MethodInfo method, IInterceptor[] interceptors)
{
if (method.IsGenericMethod && method.Name == "SetValue" || methodsToAdjust.Contains(method))
return new IInterceptor[] { proxyCellInterceptor }.Union(interceptors).ToArray();
return interceptors;
}
#endregion
}
public class ProxyCellInterceptor : IInterceptor
{
#region IInterceptor Members
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
//Wrap the return value
invocation.ReturnValue = Proxy((IXLCell)invocation.ReturnValue);
}
#endregion
public IXLCell Proxy(IXLCell target)
{
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions { Selector = new CellInterceptorSelector() };
return generator.CreateInterfaceProxyWithTarget<IXLCell>(target, options);
}
}
public class ValidateMethodInterceptor : IInterceptor
{
#region IInterceptor Members
public void Intercept(IInvocation invocation)
{
var value = invocation.Arguments[0];
//Validate the data as it is being set
if (value != null && value.ToString().Contains('\v'))
{
throw new ArgumentException("Value cannot contain vertical tabs!");
}
//Alternatively, you could do a string replace:
//if (value != null && value.ToString().Contains('\v'))
//{
// invocation.Arguments[0] = value.ToString().Replace("\v", Environment.NewLine);
//}
invocation.Proceed();
}
#endregion
}
I'm starting to dive into the world of C# Dynamics and Metaprogramming, and having some trouble.
I managed to create a CodeDom tree, and generate the following code:
namespace Mimsy {
using System;
using System.Text;
using System.Collections;
internal class JubJub {
private int _wabeCount;
private ArrayList _updates;
public JubJub(int wabeCount) {
this._updates = new ArrayList();
this.WabeCount = wabeCount;
}
public int WabeCount {
get {
return this._wabeCount;
}
set {
if((value < 0))
this._wabeCount = 0;
else
this._wabeCount = value;
this._updates.Add(this._wabeCount);
}
}
public string GetWabeCountHistory() {
StringBuilder result = new StringBuilder();
int ndx;
for(ndx = 0; (ndx < this._updates.Count); ndx = ndx + 1) {
if((ndx == 0))
result.AppendFormat("{0}", this._updates[ndx]);
else
result.AppendFormat(", {0}", this._updates[ndx]);
}
}
}
}
I am then compiling dynamically this namespace to an assembly named "dummy".
I can succesfully get an instance of this Type:
string typeName = "Mimsy.JubJub";
Type type = dummyAssembly.GetType(typeName);
dynamic obj = Activator.CreateInstance(type, new object[] { 8 });
//obj is a valid instance type
If I debug this code, I can see in the debugger that obj actually has the property WabeCount:
However, when trying to access this property, the compiler shouts that the dynamic property does not exist.
There are one or perhaps two problems with your code:
You are using an internal class, and trying to access it with dynamic. The two things don't play well together. See https://stackoverflow.com/a/18806787/613130. Use public clasas
You need to cast the value before assigning it to wabeCount, like:
obj.WabeCount = (int)wabes[ndx]
Note that technically, if your "main" assembly is strong named, you could add the InternalsVisibleToAttribute to the "dynamic" assembly to make its internal "things" visible to the main assembly... I do think it would be wasted work.
I'd like to use a web service from a database to gather informations. Right now, I implemented to web service, turned it into a proxy class via wsdl.exe but I'm slightly irritated by the outcome. The normal way to call that class is new object -> method -> parameters ->happiness. This thing only consists of partial classes and wants strange parameters. I'm not even sure if I got the right method to get the wanted information.
This seems to be the needed method:
public UniProtId2DomainIdsRecordType[] UniProtId2DomainIds (UniProtId2DomainIdsRequestRecordType UniProtId2DomainIdsRequestRecord)
{
object[] results = this.Invoke("UniProtId2DomainIds", new object[] {
UniProtId2DomainIdsRequestRecord});
return ((UniProtId2DomainIdsRecordType[])(results[0]));
}
This seems to be one of the needed classes:
public partial class UniProtId2DomainIdsRequestRecordType
{
private string uniprot_accField;
/// <remarks/>
public string uniprot_acc
{
get
{
return this.uniprot_accField;
}
set
{
this.uniprot_accField = value;
}
}
}
(That's the whole class, generated by wsdl.exe -> https://www.dropbox.com/s/yg909ibdq02js5a/GetCath.cs)
But as soon as I try to use it as I think it should work... well... my experiments on this (none of them working):
UniProtId2DomainIdsRequestRecordType Uni2Cath = new UniProtId2DomainIdsRequestRecordType();
Uni2Cath.uniprot_acc = "P0A7N9";
UniProtId2DomainIdsRecordType[] UniProtId2DomainIds;
UniProtId2DomainIdsRecordType test = new UniProtId2DomainIdsRecordType();
test.uniprot_acc = "P0A7N9";
UniProtId2DomainIdsRecordType[] UniProtId2DomainIds(test);
All I need is to get a string like P0A7N9 to be passed to the server.
(The reference to this webservice: http://api.cathdb.info/api/soap/dataservices/wsdl#op.o159501052 )
Can someone give me a hint how to handle this, please?
The easiest way would be to add this web service as Service Reference to your project. Then you can call the different methods. Use this as the address: http://api.cathdb.info/api/soap/dataservices/wsdl
using (var ser = new DataServicesPortTypeClient())
{
var results = ser.UniProtId2DomainIds(new UniProtId2DomainIdsRequestRecordType
{
uniprot_acc = "P0A7N9"
});
if (results != null)
{
var geneName = results.gene_name;
var speciesName = results.species_name;
}
}
If you want to use your generated class do this:
using (var service = new DataServices())
{
var results = service.UniProtId2DomainIds(new UniProtId2DomainIdsRequestRecordType
{
uniprot_acc = "P0A7N9"
});
if (results != null && results.Length >0)
{
var geneName = results[0].gene_name;
var speciesName = results[0].species_name;
}
}
As John suggested in the comments, ASMX and wsdl.exe are deprecated technologies. You should be using Service References and svcutil.exe
I have a dll which has some classes, these classes have some methods.
And some of those methods has another method call inside it.
How can I check whether a method inside a class has a specific method or not.
I have done some googling on this and I was able to find the classes inside the dll as follows:
public List < string > GetClassFromDlLstring(string dllName)
{
Assembly assemblies = null;
try
{
assemblies = Assembly.LoadFrom(dllName);
}
catch (Exception ex)
{
}
var allTypes = assemblies.GetTypes();
return (from allType in allTypes where allType.IsClass select allType.ToString()).ToList();
}
And similarly a method to find all the methods inside a class as follows:
public List <string> GetAllTMethodClass(string dllName, string className)
{
var assemblies = Assembly.LoadFrom(dllName);
Type type = assemblies.GetType(className);
var temp = new List <string> ();
try
{
MethodInfo[] methods = type.GetMethods();
//MethodInfo[] methods = type.GetMethods(BindingFlags.Instance);
foreach(MethodInfo meth in methods)
{
if (meth.MemberType == MemberTypes.Method && meth.MemberType != MemberTypes.Property)
temp.Add(meth.Name);
}
}
catch (Exception ex)
{
}
return temp;
}
I have a problem now the function above return property name also.
Further I want to go through the function list and check weather the function contain a particular function or not. How can I achieve this?
Edit 1:
I found the similar post whose link is below
- Look if a method is called inside a method using reflection
- Get types used inside a C# method body
You have to look into method's IL. IMO, Mono.Cecil is the best way to do this.
I'm thinking of something along the lines of the "Inline Task" in MsBuild. For reference: http://msdn.microsoft.com/en-us/library/dd722601.aspx
I'd like to find or create a framework which allows me to override a method via configuration. For example if I have a well known base class which has a method Execute(args), how can I supply an overridden method implementation at deployment time, without requiring new code, build, release cycle? I would like to actually plug in the method body into a config file or preferably a database table.
I assume this would be done either with code dom, dynamic language integration, or perhaps something like powershell(?). I'm looking for recommendations or perhaps a library someone has already written.
The application is written in C#. Preferably the extension would also be in C#, but I'm open to other ideas as well.
Update: Technically I don't even have to actually override a method. It would be sufficient to just be able to dynamically execute some external source code, passing in an arg and returning a result.
Update. I ended up writing code to instantiate a PowerShell object and execute a script dynamically to return a value. Here is a snippet of code I used.
public static Collection<PSObject> ExecuteScript(string code, string variableName, object variableValue)
{
PowerShell ps = PowerShell.Create();
ps.AddScript(code);
if (!string.IsNullOrWhiteSpace(variableName))
{
ps.Runspace.SessionStateProxy.SetVariable(variableName, variableValue);
}
var result = ps.Invoke();
return result;
}
Then in the calling code, I simply check the first PSObject in the return value, and pull the resulting value from it. It works great. Thanks for all the responses.
Here are two examples of dynamic execution. I have used neither though so I can't comment further.
http://www.codeproject.com/KB/dotnet/evaluator.aspx
http://www.csharpfriends.com/articles/getarticle.aspx?articleid=118
Regarding namespaces, from the second article you can add assemblies through the CompilerParameter class.
// Create the C# compiler
CSharpCodeProvider csCompiler = new CSharpCodeProvider();
ICodeCompiler iCodeCompiler = csCompiler.CreateCompiler();
// input params for the compiler
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.OutputAssembly = "CSharpFriends.dll";
compilerParams.ReferencedAssemblies.Add("system.dll");
One option would be to use Iron Python (or another DLR language). Your Execute method would then lookup the script in your configuration file, compile it and execute it all at runtime.
Including the necessary Iron Python assemblies with your project isn't a significant overhead.
You might need to do some plumbing to expose other parts of your application to the python runtime environment but this is quite easy to do.
You can use interfaces and then resolve the concrete classes at runtime e.g. using configuration files.
Check the various Dependency Injection Containers at http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
Managed Extensibility Framework (MEF) might be suitable as well. It was included as part of .NET 4.
http://msdn.microsoft.com/en-us/library/dd460648.aspx
http://mef.codeplex.com/
If the extensibility is just for one method then MEF would be overkill. If what you are extending will grow over time then I think MEF would provide the most robust and long-term manageable framework.
It looks like you might want to have a look at the Factory Pattern; returning delegates. Unfortunately you will need a type to 'house' the method, so you would typically generate code like:
namespace Dynamic {
public static int Foo(int bar) {
// .. Configured body here.
}
}
It's important that your factory does not generate methods it has seen before. Here is an example:
static class Delegates
{
private static Func<Func<int, string>> _test;
public static Func<int, string> Test
{
get
{
return _test();
}
}
static Delegates()
{
// Use your config variables instead of the "return arg.ToString();"
CreateFactory<Func<int, string>>(x => _test = x, "return arg.ToString();");
}
private static void CreateFactory<TDelegate>(Action<Func<TDelegate>> locationSetter, string identifier)
{
locationSetter(() =>
{
var result = Generate<TDelegate>(identifier);
locationSetter(() => result);
return result;
});
}
private static string GenerateSignature<TDelegate>()
{
// Create the signature of the delegate.
var t = typeof(TDelegate);
if (!typeof(Delegate).IsAssignableFrom(t))
throw new Exception("TDelegate must be delegate type.");
var invoke = t.GetMethod("Invoke");
var sig = new StringBuilder();
// Append the return type.
if (invoke.ReturnType == typeof(void))
sig.Append("void");
else
sig.Append(invoke.ReturnType.FullName);
sig.Append(" ");
sig.Append("Invoke(");
// Append the parameters.
var param = invoke.GetParameters();
for (var i = 0; i < param.Length; i++)
{
if (i != 0)
sig.Append(", ");
sig.Append(param[i].ParameterType.FullName);
sig.Append(" ");
sig.Append(param[i].Name);
}
sig.Append(")");
return sig.ToString();
}
private static TDelegate Generate<TDelegate>(string code)
{
// Generate the containing class and method.
var codeBuilder = new StringBuilder(50);
codeBuilder.AppendLine("using System;");
codeBuilder.Append("namespace Dynamic { class DynamicClass { public static ");
codeBuilder.Append(GenerateSignature<TDelegate>());
codeBuilder.AppendLine("{");
codeBuilder.AppendLine(code);
codeBuilder.AppendLine("} } }");
var compilerVersion = new Version(1, 0, 0, 0);
// Create the compiler parameters.
var parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = false;
parameters.ReferencedAssemblies.Clear();
foreach (var referenceAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
parameters.ReferencedAssemblies.Add(referenceAssembly.Location);
// Figure out which version we are compiling against.
var an = new AssemblyName(referenceAssembly.FullName);
if (an.Name == "mscorlib" && compilerVersion < an.Version)
{
compilerVersion = an.Version;
}
}
var cp = new CSharpCodeProvider(
new Dictionary<string, string>() { { "CompilerVersion", string.Format("v{0}.{1}", compilerVersion.Major, compilerVersion.Minor) } }
);
var results = cp.CompileAssemblyFromSource(parameters, codeBuilder.ToString());
if (results.Errors.HasErrors)
throw new Exception("Method failed to compile.");
var assembly = results.CompiledAssembly;
if (assembly == null)
throw new Exception("Method failed to compile.");
var t = assembly.GetType("Dynamic.DynamicClass");
if (t == null)
throw new Exception("Method failed to compile.");
var m = t.GetMethod("Invoke");
if (m == null)
throw new Exception("Method failed to compile.");
return (TDelegate)(object)Delegate.CreateDelegate(typeof(TDelegate), m);
}
}