Argument Confusion Running a C# Method In IronPython - c#

I am trying to run a c# method in the IronPython (2.7.3) console:
The c# (compiled to a dll) is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PythonTest
{
public class PythonTest
{
public PythonTest(){}
public int GetOne()
{
return 1;
}
public double Sum(double d1, double d2)
{
return d1+d2;
}
public string HiPlanet()
{
return "Hi Planeta";
}
}
}
the python is
import sys
sys.path.append("Y:\\")
import clr
clr.AddReferenceToFile('./PythonTest')
import PythonTest
a = PythonTest.PythonTest.GetOne()
I get a TypeError in ironpython saying that the function takes one arguement (which it doesn't according to my c#!). I am confused and woudl appeciate help here, I'm just trying to call some c# functions provide the arguements and get the results, thanks in advance!

Since it's an instance method, you need to instantiate the object before calling GetOne method:
obj = PythonTest.PythonTest()
a = obj.GetOne()
or, in one-liner:
a = PythonTest.PythonTest().GetOne()

Related

How can I turn a string into a runnable piece of code in c#

In a program I'm creating, I need to be able to convert a string variable into a runnable piece of code in C#.
For example we would have
String code = "console.Writeline("hello");"
function(code);
double function(String var) {
// turn var into code
// run var
}
Any feedback would be much appreciated.
You can use lprun.exe which comes with LINQPad. The documentation explains the usage pretty well.
In summary you pass in your C# (also other languages available) code which is let's say stored in Foo.txt to the executable which is then executed.
lprun.exe -lang=p Foo.txt
p stands for Program see the documentation for more details.
You need to actually compile the method on runtime to use them like this (ie. pass method by string and then compile it).
So for example you can:
Create method on runtime
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
public static class RuntimeHelpers
{
public static MethodInfo CreateFunction()
{
//You can pass it through parameter
string code = #"
using System;
namespace RuntimeFunctions
{
public class Functions
{
public static void PrintStuff(string input)
{
Console.WriteLine(input);
}
}
}";
//Compile on runtime:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults results = provider.CompileAssemblyFromSource(new CompilerParameters(), code);
//Compiled code threw error? Print it.
if (results.Errors.HasErrors)
{
foreach (var error in results.Errors)
{
Console.WriteLine(error);
}
}
//Return MethodInfo for future use
Type function = results.CompiledAssembly.GetType("RuntimeFunctions.Functions");
return function.GetMethod("PrintStuff");
}
}
Use it
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
MethodInfo info = RuntimeHelpers.CreateFunction();
//Create delegate to use our function
//If you're gonna create function that actually returns something,
//you need to go for a Func<T, T1> cast instead of Action<T>
var func = (Action<string>)Delegate.CreateDelegate(typeof (Action<string>), info);
func("Hello");
Console.ReadKey();
}
}
Loosely based on article by Lumír Kojecký on: http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime

Why I have to write the namespace to access to this extension method?

I have a project that has class to implement extension methods for some type. For example I have this class for ObservableCollection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace MyProject.Collections.Utils
{
public static class ObservableCollection
{
public static void RemoveAll<T>(this ObservableCollection<T> collection, Func<T, bool> condition)
{
for (int i = collection.Count - 1; i >= 0; i--)
{
if (condition(collection[i]))
{
collection.RemoveAt(i);
}
}
}//RemoveAll
}
}
With this class, in my main project I can use this library with the using:
using MyProject.Collections.Utils
And when I want to use the extension methods I can do:
ObservableCollection<MyType> myOC = new ObservableCollection<MyType>();
myOC.RemoveAll(x=>x.MyProperty == "123");
So I have access to my extension method.
However, I have another class for Decimal, is this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyProject.Decimal.Utils
{
public static class Decimal
{
public static decimal? Parse(this string paramString)
{
try
{
myCode
}
catch
{
throw;
}
}//Parse
}
}
But in this case, although in my main prject I import the class:
using MyProject.Decimal.Utils;
If I do this:
decimal? myDecimalParsed= Decimal.Utils.Decimal.Parse("123");
Why in this case I can't do this?:
decimal? myDecimalParsed= decimal.Parse("123");
thank so much.
Two problems:
You can't use extension methods as if they were static methods of the extended type
System.Decimal already has a Parse method, and the compiler always looks for "real" methods before extension methods.
In fact, you can write
decimal? miTiempoEstimadoParseado = decimal.Parse("123");
... but that will just call the normal method and then convert the decimal to decimal? implicitly in the normal way.
Note that you're not really using your method as an extension method at the moment anyway - to do so you'd write something like:
decimal? miTiempoEstimadoParseado = "123".Parse();
... but personally I'd view that as pretty ugly, partly as the method name doesn't indicate the target type at all, and partly because by convention Parse methods throw an exception instead of returning a null value on failure. You probably want to come up with a different name.

initializecomponent() don't exist in current context while using generics in c# web application

I am trying to create a generics in c# web application and using silverlight-5. This i have already implemented in c# console application.
I am trying to do same in webdevelopment using asp.net,c# and silverlight (and GUI using xaml) in Vs-2010. Whose GUI is displayed on internet explorer on running the code (by button click events).
In console application i do so by following code : (The code is to read a binary file as sole argument on console application and read the symbol in that file, These symbol could be int32/int16/int64/UInt32 etc.). So have to make this Symbol variable as "generic"(<T>). And in console application this code works fine.
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace check
{
LINE:1 public class Huffman < T > where T: struct,IComparable < T >,IEquatable < T >
{
public int data_size, length, i, is_there;
public class Node
{
public Node next;
line:2 public T symbol; // This symbol is of generic type.
public int freq;
}
public Node front, rear;
LINE:3 public Huffman(string[] args, Func < byte[], int, T > converter)
{
front = null;
rear = null;
int size = Marshal.SizeOf(typeof (T));
using(var stream = new BinaryReader(System.IO.File.OpenRead(args[0])))
{
long length = stream.BaseStream.Length;
for (long position = 0; position + size < length; position += size)
{
byte[] bytes = stream.ReadBytes(size);
LINE:4 T processingValue = converter(bytes, 0); //**Here I read that symbol and store in processing value which is of type <T>**
//Then further i use this processingValue and "next" varible(which is on Node type)
}
}
}
}
public class MyClass
{
public static void Main(string[] args)
{
line:5 Huffman < long > ObjSym = new Huffman < long > (args, BitConverter.ToInt64);
// It could be "ToInt32"/"ToInt16"/"UInt16"/"UInt32"/"UInt64" with respective
//change in <int>/<short> etc.
//Then i further use this ObjSym object to call function(Like Print_tree() here and there are many more function calls)
ObjSym.Print_tree(ObjSym.front);
}
}
}
The same thing i have to achieve in C# silverlight(web application) with a difference that i have already uploaded and stored the file by button click (By Browsing it)(whereas i was uploading/reading file as sole argument in console application), This file upload part i have already done.
The problem now is how to make this "symbol" variable generic(<T>) here because i am not able to see any Object creation (In main(string[] args) method) where i could pass parameter BitConverter.ToInt32/64/16 (as i am doing in console application, please see code).
NOTE: please see that i have used in LINE 1,2,3,4,5 in my code (so that the same(or different if you have other approach) has to be achieved in the code below to make "symbol" of type )
Because in c# i get body of code like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace check
{
public partial class MainPage : UserControl
{
public class Node
{
public Node next;
public long symbol; // This symbol is of generic type.
public int freq;
}
public Node front, rear;
public MainPage()
{
InitializeComponent();
}
}
}
Could some one please help me in changing the code of this web application exactly similar to that console application code (I mean making "Symbol variable as generic(<T>)")
EDIT: When i do this:
(1) public partial class MainPage <T> : UserControl, IComparable < T > where T: struct,IEquatable < T >
(2) public T symbol; (In Node class)
(3) And all the buttons and boxes i created are given not existing in current context.
then it gives error
Error :The name 'InitializeComponent' does not exist in the current context
Could some one please help me in achieving the same in c# silverlight web application ? Would be a big help,thanks.
Here is a Example.
namespace check
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
// Use the generic type Test with an int type parameter.
Test<int> Test1 = new Test<int>(5);
// Call the Write method.
Test1.Write();
// Use the generic type Test with a string type parameter.
Test<string> Test2 = new Test<string>("cat");
Test2.Write();
}
}
class Test<T>
{
T _value;
public Test(T t)
{
// The field has the same type as the parameter.
this._value = t;
}
public void Write()
{
MessageBox.Show(this._value);
}
}
}
I think you asking this kind of example.
You can use generic as if you don’t use XAML. But if you want to use XAML to define your control, you can’t use generic. That's why the problem is occurs.
Create a another class and use it. I think It's help you.

C# Beginner problems

I have a "Debug" class, which simply prints information to the console etc. From the rest of the code I want to be able to call the methods within it, but so far it's only partly working.
Calling dc.Print() works fine, but as soon as I call dc.Print(dc.GetEventsLogged()) I get a red line with the message
"The best overloaded method match has some invalid arguments" as well as Argument 1: cannot convert from 'int' to 'string'.
Basically: Why are my arguments to dc.Print wrong? Also, what can I do about "cannot convert from int to string? I tried .ToString but that didn't work either.
This is my "Debug.cs" class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
public class Debug
{
private int events_logged;
public Debug()
{
events_logged = 0;
}
public void Print(string Message)
{
Console.WriteLine("[" + DateTime.UtcNow + "] " + Message);
events_logged++;
}
public int GetEventsLogged()
{
return events_logged;
}
}
}
And in my "Program.cs" class I have:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
class Program
{
static void Main(string[] args)
{
Debug dc = new Debug();
dc.Print("Test");
}
}
}
The reason you are seeing the error is because GetEventsLogged() returns an int whereas Print() expects you to pass in a string. Therefore you need to the return from int to string and you were on the right track with ToString(). This will do what you want to achieve:
dc.Print(dc.GetEventsLogged().ToString());
dc.Print() wants a string argument and dc.GetEventsLogged() returns an int. You need to ToString() the int so that the types match.
int numberOfEventsLogged = dc.GetEventsLogged();
string numberOfEventsLoggedAsString = numberOfEventsLogged.ToString();
dc.Print(numberOfEventsLoggedAsString)
try dc.Print(dc.GetEventsLogged().toString()) because GetEventsLogged() is of int type and Print(string Message) looking for string input.
Your method Print expects an argument of type String. When you call dc.Print(dc.GetEventsLogged()), your actually give an int because your method GetEventsLogged() returns an int.
public string GetEventsLogged()
{
return events_logged.ToString();
}

Expose dll for COM Interop

I thought I knew how to do this, but obviously not so I'd appreciate some help!
I can't get my dll to register so I can instantiate it in a VBS, or elsewhere.
I wrote the following sample class, checked "Make assembly COM Visible", checked "Register for COM Interop", then built it.
When I try to instantiate it from VBS I get the "Activex component can't create object" error.
This is the class code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Smurf
{
public class Pants
{
public string Explode(bool Loud)
{
string result;
if (Loud)
result = "BANG";
else
result = "pop";
return result;
}
}
}
...and this is the VBS:
Dim a
Set a = CreateObject("Smurf.Pants")
msgbox("ok")
What else do I need to do?
Thanks :)
[edit]
Forgot to mention, after the first failure I tried REGSVR32 and REGASM - no help!
[/edit]
Note that when I try REGSVR32, I get this message:
The Module "C:...\Smurf.dll" was loaded but the entry-point DllRegisterServer was not found.
Make sure that "C:...\Smurf.dll" is a valid DLL or OCX file and then try again.
How helpful is that??
This is the latest version of the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Smurf
{
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IPants
{
[DispId(1)]
string Explode(bool Loud);
}
[Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IPantsEvents
{
string Explode(bool Loud);
}
[ComVisible(true)]
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(IPantsEvents))]
public class Pants : IPants
{
public Pants() { }
[ComVisible(true)]
[ComRegisterFunction()]
public static void DllRegisterServer(string key) { }
[ComVisible(true)]
[ComUnregisterFunction()]
public static void DllUnregisterServer(string key) { }
[ComVisible(true)]
public string Explode(bool Loud)
{
string result;
if (Loud)
result = "BANG";
else
result = "pop";
return result;
}
}
}
There could be a few different things at play here. First, you'll want to use the regasm tool with the /codebase /tlb switch from an elevated command prompt (assuming Windows Vista, 7 or Windows Server 2008). Something like:
regasm "Path to Smurf.dll" /codebase /tlb
Once you have registered the dll using regasm you should be able to invoke it using VBS, VBA or VB6.
I was able to use early binding and late binding from VBA to call the Explode method. However, when I tried from VBScript I received the "ActiveX can't create object error as you did."
I'm running on Windows 7 64 bit, and I recalled that this can cause problems when compiling to 32 bit dlls and running them on 64 bit operating systems. On a whim, I fired up a command prompt and entered:
C:\Windows\SysWow64\CScript.exe "Path to VBScript"
The result was that the script ran correctly and displayed "Pop" on screen.
Here's the somewhat simplified C# code I used as well as the contents of the VBScript file.
namespace Smurf
{
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IPants
{
string Explode(bool Loud);
}
[Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IPantsEvents
{
string Explode(bool Loud);
}
[ComVisible(true)]
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938")]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IPantsEvents))]
public class Pants : IPants
{
[ComVisible(true)]
public string Explode(bool Loud)
{
string result;
if (Loud)
result = "BANG";
else
result = "pop";
return result;
}
}
}
VBScript:
Dim x
Set x = CreateObject("Smurf.Pants")
MsgBox (x.Explode(False))
Set x = Nothing

Categories

Resources