I am looking at Amibroker's OLE documentation examples in VBScript and JS trying to convert it to C# code:
http://www.amibroker.de/guide/objects.html
In it it says:
Filter( 0, "index" ) = 1; // include only indices
Filter( 1, "market" ) = 2; // exclude 2nd market
I have a C# dynamic object that I built, and I can find and call the Filter() function, but I have no idea how to set the value after the function call, since that is not valid C# syntax.
Here is the C# code:
var type = Type.GetTypeFromProgID("Broker.Application");
dynamic ab = Activator.CreateInstance(type);
ab.Analysis.Filter(0, "market") = 2; // This is obviously not compiling
When I call ab.Analysis.Filter(0, "market"), it simply returns an int for the current setting. Is the answer to use reflection somehow? I haven't tried to go down that route wondering if there is a simpler solution.
That code snippet you found is jscript, not VBScript. It is not a function property, it is an indexed property. VB.NET supports them well. But the C# team did not like them and only permits one indexed property for a class, the indexer (this[]). By popular demand they added support in version 4. Only for COM interop. Which is what you are using.
Just like the indexer, you use square brackets for indexed properties:
AA.Filter[0, "market"] = 1;
Which should be supported by dynamic as well. Explicitly calling the setter function would be another way, AA.set_Filter(0, "market", 1).
Note that you'll have a much easier time writing this code when you add a reference to the type library. That lights up IntelliSense and the red squiggles.
Related
I am converting a large VB.Net project to C#. I used an free automated tool to convert them. VB is happy with empty parameters passed in and uses default values for them supplied in the method definition.
After the conversion, there are many calls in the C# code looking like this:
GetElement(ndFirst, WAIT_AFTER_BATCH,false, , , "WAIT");
And compiler is not happy...
Can someone point me in the right direction if I can edit the C# files automatically(since intellisense knows how to) to fill these default values when I am making the call.
I am assuming that the C# version of your methods has the default parameters specified correctly, ex.
public void SomeMethod(int paramA = 0, int paramB = 1, int paramC = 2){
...
}
If you want to call the method and accept the default for paramB (as in your example), then you need to name the parameters
SomeMethod(paramA: 12, paramC: 20);
This would collect values for paramA and paramC whilst using the default for paramB.
Furthermore, since paramA is in the correct position, this will also be correct
SomeMethod(12, paramC: 20);
Alternatively, if the parameter you want to leave out is the last one, you can simply leave it out and call your method like so
SomeMethod(12,20);
Where paramA = 12, paramB = 20 and paramC will use the default of 2.
Unfortunately I am unaware of an automatic way to fix these. Likewise, to speed you up, you can use ReSharper and create a formatter to enforce using named arguments. Then run a simple regex over your project and clean out any instances of ',,'
Note I am in no way affiliated with JetBrains or ReSharper. I am a mere client of this company.
I have also experience that when i shifted from VB.Net to C#.Net
Here's what you will do:
First of all import InteropServices NameSpace
using System.Runtime.InteropServices;
Then create a function or procedure like this one below: (in my case it's a function)
static string ResizeImage(string imgTemp,
[Optional, DefaultParameterValue(200)] int xLength)
{
// Do something HERE
}
I fixed the compiler errors in generated cs files for the common libraries
Wrote a utility that goes over the method definitions in the file and prepared a catalog of the methods and ParamterInfos in a dictionary.
var methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
//this is not exact for methods with different signatures.
foreach (var methodInfo in methodInfos)
{
if(!methodCatalog.ContainsKey(methodInfo.Name))
methodCatalog.Add(methodInfo.Name, methodInfo.GetParameters());
else
{
methodCatalog.Add(methodInfo.Name + "__" + Guid.NewGuid() , methodInfo.GetParameters());
}
}
Wrote another method where I tokenize a line for the method call get the method parameters (they are all "," seperated)
For the empty parameter values I set the values from my method dictionary
for(int i = 0; i < paramValues.Length; i++)
{
if( string.IsNullOrEmpty( paramValues[i].Trim()) )
{
paramValues[i] = currentParameterInfos[i].DefaultValue.ToString();
}
}
This is error prone but it is better than goin in the files and editing them by hand.
I followed the link of parse CSV using F# and filehelpers. got compiler error for the following code "The record class oneRow need a constructor with no args (public or private)"
[<DelimitedRecord(",")>]
type oneRow=
class
[<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
val date: DateTime
val value: bool
end
let engine = new FileHelperEngine(typeof<oneRow>)
let tmp = engine.ReadFile("test.csv")
EDIT
The solution looks quite verbose than c# version. I need add (), mutable and [<DefaultValue>]
type oneRow() =
class
[<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
[<DefaultValue>]
val mutable date: DateTime
[<DefaultValue>]
val mutable value: bool
end
But similar code works in C# without specify a constructor. Could anyone help me fix the F# code? thanks.
C# will create you a constructor. F# doesn't (presumably because parameterless constructors imply mutability, and so are not exactly encouraged.)
For example, in your code - how are you going to set those properties, they're still immutable.
Regarding the verbose syntax - It can be made nicer. The sample was written some time ago (2 years), so it is still using a little old syntax. It could be updated to allow writing something like this:
[<DelimitedRecord(",")>]
type OneRow
( [<FieldConverter(ConverterKind.Date, "M/d/yyyy")>]
date:DateTime,
value:bool ) =
member x.Date = date
member x.Value = value
I believe this is a lot nicer (and by moving annotations to the constructor, you can also implement your own functionality in the type and e.g. hide some fields). The only change that needs to be done is to modify the parser to find attributes on constructor parameters (and not fields).
Based on the error message, i think it would work if a ctor is added into oneRow.
new () = { date = new DateTime() ; value = false}
yes, it should be type oneRow () = with parentheses
Most of the posts concerning FileHelpers are rather dated. In some cases though it's nice to use instead of the csv type provider. One can use the CLIMutable attribute on an F# record to have a default constructor and in this case FileHelpers will happily write and read the csv file:
#if INTERACTIVE
#I #"..\packages\FileHelpers\lib\net45"
#r "FileHelpers.dll"
#endif
open FileHelpers
open System
[<DelimitedRecord(",");CLIMutable>]
type TestFileHelp =
{test1:string
test2:string
[<FieldConverter(ConverterKind.Date, "yyyy/MM/dd")>]
date:DateTime
}
let f1 = [|{test1="a";test2="b";date=DateTime.Now};{test1="c";test2="d";date=DateTime.Now}|]
let fengine = new FileHelperEngine<TestFileHelp>()
fengine.WriteFile(#"c:\tmp\testrec.csv",f1)
One of the common programming best practices is "define variables as close to where they are used as possible".
I use structs frequently to create code thats almost self documenting in places. However, C# forces me to define the struct outside the method. This breaks the aforementioned best practice - its basically creating an unwanted global variable type for the entire class.
Is it possible to define a local struct inside a method, just like a local variable, and if not, could you give me a window into the reasons the C# designers decided to prevent this?
Use Case
I'm converting part of a spreadsheet into C# code. I'd like to use local structs within the method to store temporary information in an organized manner, without having to resort to hundreds of separate variables that are global in scope.
Update 2016-August: C# 7.0 may have this feature!
As of 2016-Aug, apparently, this will be a feature in C# 7.0.
So the C# compiler team agreed - wow!
Update 2020-July: Now supported by C# and C++
C++ has always fully supported this. And it's fantastic.
C# 7.0 now has value tuples for a lightweight data structure with named fields. See answer from Ghost4Man.
I believe it's not permitted to define named types within a method. As to why, I'll have to speculate. If a type is not going to be used outside, then its existence probably cannot be justified.
You can however define anonymous type variables within a method. It will somewhat resembles structures. A compromise.
public void SomeMethod ()
{
var anonymousTypeVar = new { x = 5, y = 10 };
}
It is a little late but this is my solution for lists - using anonymous vars as the structs inside of methods:
var list = new[] { new { sn = "a1", sd = "b1" } }.ToList(); // declaring structure
list.Clear(); // clearing dummy element
list.Add(new { sn="a", sd="b"}); // adding real element
foreach (var leaf in list) if (leaf.sn == "a") break; // using it
Anonymous elements (sn and sd) are somehow read only.
Since C# 7.0, you can use value tuples if you want a lightweight data structure with named fields. They can be used not only locally inside methods, but also in parameters, returns, properties, fields, etc. You can use local functions to somewhat emulate struct methods.
var book = (id: 65, pageCount: 535); // Initialization A
(int id, int pageCount) book2 = (44, 100); // Initialization B
Console.WriteLine($"Book {book.id} has {book.pageCount} pages.");
(int id, int pageCount) = book; // Deconstruction into variables
Console.WriteLine($"Book {id} has {pageCount} pages.");
Here book is of type System.ValueTuple<int, int> (a generic struct).
You could do something like this using anonymous types. MSDN examples below:
var v = new { Amount = 108, Message = "Hello" };
or
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Nowadays, you could also use a named tuple: https://learn.microsoft.com/en-us/dotnet/csharp/tuples
No, this is not possible. If you are using .net 4.0, you could use Tuple<T1, ..., Tn> to replicate such a thing.
I don't see the reason why you would need such a struct - just use variables with speaking names and this shouldn't be any problem at all. In combination with explicit declaration using the class names there is very little space for ambiguity.
You can define an anonymous type within your method and use it. The anonymous type will be readonly, so it gets you the immutability that is desired of structs. It will not explicitly be a struct, but it will be fully defined and contained within your method.
var myLocalType = new
{
SomeValue = "Foo",
SomeId = 14
};
it's not a struct, but mayme a var can help you out here?
var person = new {Name= "John", City = "London"};
it's strong typed so it will be compile time checked
You can create a dynamic type in c# 4.0 to accomplish this task, but its not exactly what you are looking for.
However I believe that the maximum of defining variables as close to where they are used is meant to mean where a variable is introduced into program flow not where the type is declared. I believe that most types have some ability to be reused creating in method types limits you ability to create reusable blocks of code that operates on common data.
Hello everyone I am trying to cast two objects to, both, a specific type based on property reflection information. I want to do this dynamically so I don't need a bunch of switch cases and such for each type that the two objects can be in this class. Overall they will mostly be int or float. At the moment I currently tried using 'var' and 'object' keywords to hold the incoming adjustment value and the properties original value.
// .. snip
/* Get property information. */
PropertyInfo propInfo = classObj.GetType().GetProperty("property-name");
if (propInfo == null)
continue;
/* Prepare object values. */
object orgVal = propInfo.GetValue( classObj, null );
object adjVal = Convert.ChangeType( strAdjust, propInfo.GetType(), new CultureInfo("en-us"));
// .. math on objects here
// ex. orgVal += adjVal;
// .. snip
The incoming adjustment value is in a string but is either in 'int' or 'float' format so it will be easily converted. All of this works fine, it's just the casting to be allowed to adjust the original value with the new adjustment value that is the issue.
I know with .NET 4.0 there is the 'dynamic' keyword that would be able to accomplish something like this, but currently I am stuck using 3.5.
Both objects will use the type from the property information propInfo.GetType().
Any help with this would be greatly appreciated, I'm sure I'm probably overlooking a basic thing here to get this accomplished. Thanks in advance.
-CK
Edit:
Forgot to mention, sorry, this is being developed on a Zune HD, so the framework I have access to is fairly limited to what can/can't be used.
C# 3.5 has a class called TypeConverter
http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx
These provide a mechanism of converting from one type to another based on type information.
System.ComponentModel.TypeConverter GetConverter(System.Type type)
is used to get the converter and
public object TypeConverter.ConvertFrom(object value)
does the conversion. There are built in converters for basic types like int and float, and it is possible to write custom converters for your own types.
Microsoft has a guide to writing them here.
http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx
There's a couple of ways you can do this that I can think of. You can use reflection to get the "op_Addition" method (which is basically "operator +"). But the way I'd do it is via Lambdas:
var orgValueParam = Expression.Parameter(propInfo.PropertyType, "lhs");
var adjValueParam = Expression.Parameter(propInfo.PropertyType, "rhs");
var expr = Expression.Add(orgValueParam, adjValueParam);
var func = Expression.Lambda(expr, orgValueParam, adjValueParam).Compile();
var result = func(orgValue, adjValue);
Note: I haven't actually tested this, so I don't know whether it'll work for sure, but that's where I'd start...
I have inherited a small scripting language and I am attempting to port it to the DLR so that it is a little easier to manage. So far it has been fairly straight forward. I have run into a problem though attempting to dynamically call members of a variable. The current language runs on .NET and uses a parsing loop and reflection to do this, but I was hoping to get away from that. Here is an example of the script language:
string $system1RemoteUri;
string $dbconnection = $config.GetDBConnection ("somedb");
float $minBad = 0.998;
float $minGood = 0.2;
$systen1RemoteURI, $minBad, and $minGood are variables that will be set in the script, along with $dbconnection. However $dbconnection will get its value from a variable passed in called $config. The 4 variables need to be available to the caller, so they are passed into the lambda, initially as null. Here is the generated Lambda IL (debug view):
.Lambda #Lambda1<Delegate6$1>(
System.String& $$system1RemoteUri,
System.String& $$dbconnection,
System.Double& $$minBad,
System.Double& $$minGood
System.Object $$config) {
.Block() {
$$minBad = 0.998D;
$$minGood = 0.2D
}
//Some assignment similar to...
//.Dynamic Call GetDBConnection($config, "somedb");
}
What I am trying to figure out is how to use Expression.Dynamic to emit the $config.GetDBConnection("somedb"). From looking at examples in the Sympl libraries I believe the emitted IL should look like:
.Dynamic Call GetdbConnection($config, "somedb") but I cant figure out how to actually emit that from Expression.Dynamic.
It seems to want a CallSiteBinder which I cannot create correctly, and I do not understand what the order of parameters is to Expression.Dynamic, as it seems to only want the "member" being invoked, and not the base.
I do not know the runtime type of $config it is just some object which implements a function called GetDBConnection(string). This is not provided by an interface or base class.
Any help would be appreciated.
You can either turn this into an InvokeMemberBinder or turn "$config.GetDBConnection" into a GetMember and then do an Invoke on the result of that passing $someDb as the argument.
To implement your GetMemberBinder and InvokeMemberBinder you can use the DLR outer-layer DefaultBinder class. In the latest IronPython/IronRuby source code you can just create a new DefaultBinder instance out of thin air. Then in your FallbackGetMember / FallbackInvoke you can call defaultBinder.GetMember(...) and defaultBinder.Call (which should be renamed Invoke). That'll deal with most .NET types for you. Also all objects which implement IDynamicMetaObjectProvider will work with it as well. For other dynamic operations you can use the other methods on the default binder. And if you want to start customizing your overload resolution and binding rules it has lots of knobs you can turn.
Unfortunately the default binder doesn't have an InvokeMemberBinder implementation right now so you're probably better off w/ GetMember/Invoke.