How can call instance by COM? - com

I try to call skype instance by COM on F#.
A aim is get mood message.
test.fs
// Import skype4com Api
open SKYPE4COMLib
type SKYPE4COM =
new() = new SKYPE4COM()
let GetMood =
let aSkype = new SKYPE4COM
mood <- aSkype.CurrentUserProfile.MoodText
mood
But when build(before too),error occur.
Incomplete structured construct at or before this point in expression
Thanks in advance.
this is next version what I think.
test01.fs
// Import skype4com Api
open SKYPE4COMLib
let GetMood =
let aSkype = new SKYPE4COMLib() // line 1
mood <- aSkype.CurrentUserProfile.MoodText // line 2
mood // line 3
error message(when building).
line in 1:error FS0039: The type 'SKYPE4COMLib' is not defined
line in 2:error FS0039: The value or constructor 'mood' is not defined
line in 3:error FS0039: The value or constructor 'mood' is not defined
also like that...

Your code has several issues. First of all, your constructor for the SKYPE4COM class appears to be recursive (?!), which is going to cause a stack overflow if you try to create an instance. Secondly, the error that you're receiving is because you are using the new operator, but you haven't completed the call to the constructor (i.e. you need to apply the constructor using parentheses: let aSkype = new SKYPE4COM()). Even then, though, you've got another issue because your type doesn't expose a CurrentUserProfile property, so your code still won't work.
Try something like this:
open SKYPE4COMLib
let getMood() =
SkypeClass().CurrentUserProfile.MoodText

Consider using a Type Extension to add a member to an already existing type:
open SKYPE4COMLib
type SKYPE4COMLib with
member this.GetMood() =
aSkype.CurrentUserProfile.MoodText
This would allow you to access GetMood as if it were a member function defined on the SKYPE4COMLib type:
let x = new SKYPE4COMLib()
printfn "%A" (x.GetMood())

Related

Replacing Type with var for all 'Class class = new Class()' usages in Java project

I recently switched to Java 11 for a rather big project, and would like to switch to using var class = new Class() instead of Class class = new CLass().
I tried using Intellij Structural Search (and replace) for this, but its turning out to be more complex than expected.
My first attempt was $Type$ $Inst$ = new $Constructor$($Argument$);, which also matches global variables (which don't allow var).
My second attempt is:
class $Class$ {
$ReturnType$ $Method$ ($ParameterType$ $Parameter$) throws $ExceptionType$ {
$Statements$;
final $Type$ $Inst$ = new $Constructor$($Argument$);
$Statements2$;
}
}
Which misses all calls inside e.g. try blocks (since they get matched by the expressions)
Any help would be greatly appreciated!
Use your first template
$Type$ $Inst$ = new $Constructor$($Argument$);
But add a Script modifier on the $Inst$ variable with the following text:
Inst instanceof com.intellij.psi.PsiLocalVariable
Alternatively you may want to try the Local variable type can be omitted inspection that is available in IntelliJ IDEA.

Inject Method with Mono.Cecil

How can I inject a custom method into a .net assembly using mono.cecil, and then call it in the entrypoint?
I like to do this to implement security methods after the binary is built.
To inject method you need to get the type you want to add it the method and then add a MethoDefinition.
var mainModule = ModuleDefinition.ReadModule(assemblyPath);
var type = module.Types.Single(t => t.Name == "TypeYouWant");
var newMethodDef= new MethodDefinition("Name", MethodAttributes.Public, mainModule.TypeSystem.Void);
type.Methods.Add(newMethodDef);
To call this method form the entry point, you need to get the entry point MethodDefinition and the new injected MethodReference and add instruction in the entry point method to call the new injected method.
var newMethodRef = type.Methods.Single(m => m.Name == "Name").Resolve();
var entryPoint= type.Methods.Single(m => m.Name == "YourEntryPoint");
var firstInstruction = entryPoint.Body.Instructions.First();
var il = entryPoint.Body.GetILProcessor();
il.InsertBefore(firstInstruction, Instruction.Create(OpCodes.Callvirt, newMethodRef));
mainModule.Write(assemblyPath);
Note: Yes I know its C# and not VB but I'm sure once you got the idea you can easily convert it to VB.
You can make use of the Module.Import() function.
Example Class can be seen in the video:
https://www.youtube.com/watch?v=heTCisgYjhs
Credits to TheUnknownProgrammer's importer class.

Ability to set the context of the expression

Is there a way to set the context of the expression in Dynamic Expresso library, so that we can do something like the following:
interpreter.Eval("FirstName", new Parameter("person", new { FirstName="Homer", LastName="Simpson"}));
rather than
interpreter.Eval("person.FirstName", new Parameter("person", new { FirstName="Homer", LastName="Simpson"}));
Maybe we could have a another option that would say that the first parameter is to be used as the context for the expression.
I guess there could also be another version of Parse and Eval methods that simply takes the expression text and a simple object value that will serve as the expression context.
Other than that and the lack of support for dynamic types, I am really liking this library. I had worked on something similar, but had not added support for extension methods and generic method calls.
Thanks for the great library,
Neal
There isn't a built-in solution but you can simulate it in many ways:
Option 1: Inject an expression
var workingContext = new { FirstName = "homer" };
var workingContextExpression = Expression.Constant(workingContext);
var firstNameExpression = Expression.Property(workingContextExpression, "FirstName");
var interpreter = new Interpreter();
interpreter.SetExpression("FirstName", firstNameExpression);
Assert.AreEqual(workingContext.FirstName, interpreter.Eval("FirstName"));
Basically I inject an expression using SetExpression method. The injected expression is the property that you want to be available.
Option 2: Use this/me/it variable
You can inject a variable that will contain your working object. I usually call it this (or me or it depending on the application).
var workingContext = new { FirstName = "homer" };
var interpreter = new Interpreter();
interpreter.SetVariable("this", workingContext);
Assert.AreEqual(workingContext.FirstName, interpreter.Eval("this.FirstName"));
Option 3: A combination of the previous solutions
var workingContext = new { FirstName = "homer" };
var interpreter = new Interpreter();
interpreter.SetVariable("this", workingContext);
var firstNameExpression = interpreter.Parse("this.FirstName").LambdaExpression.Body;
interpreter.SetExpression("FirstName", firstNameExpression);
Assert.AreEqual(workingContext.FirstName, interpreter.Eval("FirstName"));
Equal to the first solution but I generate the expression using the parser itself.
Consider that all solutions assume that you must have an Interpreter instance for each context.
Disclaimer: I'm the author of Dynamic Expresso library.
Starting with DynamicExpresso v2.13.0, it's possible to define a variable named "this", that will be used for implicit resolution:
var target = new Interpreter();
target.SetVariable("this", new { FirstName="Homer", LastName="Simpson"});
// 'this' variable is used implicitly
Assert.AreEqual("Homer", target.Eval("FirstName"));
// 'this' variable can also be used explicitly
Assert.AreEqual("Homer", target.Eval("this.FirstName"));

Creating WCF service by determining type at runtime

I am trying to create a WCF service without knowing its type/interface at runtime. To do this, I use ChannelFactory. ChannelFactory is a generic class so I need to use Type.MakeGenericType. The type I pass to MakeGenericType is from a list of interfaces I previously gathered with reflection by searching some assemblies.
Ultimately, I call MethodInfo.Invoke to create the object. The object is created just fine, but I cannot cast it to the proper interface. Upon casting, I receive the following error:
"Unable to cast transparent proxy to type 'Tssc.Services.MyType.IMyType'"
After some experimenting, I have found that the interface/type passed to MakeGenericType seems to be the problem. If I substitute the interface in my list with the actual interface, then everything works fine. I have combed through the two objects and cannot see a difference. When I modify the code to produce both types, comparing them with Equals returns false. It is unclear to me whether Equals is just checking that they are referring to the same object (not) or thety are checking all properties, etc.
Could this have something to do with how I gathered my interfaces (Reflection, saving in a list...)? A comparison of the objects seems to indicate they are equivalent. I printed all properties for both objects and they are the same. Do I need to dig deeper? If so, into where?
// createService() method
//*** tried both of these interfaces, only 2nd works - but they seem to be identical
//Type t = interfaces[i]; // get type from list created above - doesn't work
Type t = typeof(Tssc.Services.MyType.IMyType); // actual type - works OK
// create ChannelFactory type with my type parameter (t)
Type factoryType = typeof(ChannelFactory<>);
factoryType = factoryType.MakeGenericType(new Type[] { t });
// create ChannelFactory<> object with two-param ctor
BasicHttpBinding binding = new BasicHttpBinding();
string address = "blah blah blah";
var factory = Activator.CreateInstance(factoryType, new object[] { binding, address });
// get overload of ChannelFactory<>.CreateChannel with no parameters
MethodInfo method = factoryType.GetMethod("CreateChannel", new Type[] { });
return method.Invoke(factory, null);
//--------------- code that calls code above and uses its return
object ob = createService();
//*** this cast fails
Tssc.Services.MyType.IMyType service = (Tssc.Services.MyType.IMyType)ob;
Ok, I understand whats happening here - the problem is relating to loading the same assembly being effectively loaded twice - once via a reference, and once via the assembly load command. What you need to do is change the place where you load your assembly, and check to see if it already exists in the current AppDomain, like this maybe:
Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals("ClassLibrary1Name"));
if (assembly == null)
{
assembly = System.Reflection.Assembly.LoadFile("path to your assembly");
}
//do your work here
This way if the assembly is already loaded into memory, it'll use that one.

How can I set up expectations for event registration on a multimock

I am using RhinoMocks 3.6 and would like to use the multimock feature to implement both a class and a interface.
var mocks = new MockRepository();
var project = mocks.StrictMultiMock(
typeof(Project),
typeof(INotifyCollectionChanged));
using (mocks.Record())
{
((INotifyCollectionChanged)project).CollectionChanged += null;
LastCall.Constraints(Is.NotNull()).Repeat.Any();
}
The LastCall is working though. I get this message :
System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).
What am I doing wrong here??
Have you actually checked that the Project class has methods you can override as the error message indicates? I'll assume you have. :-)
I'd suggest you switch to using the AAA syntax instead of record/replay as shown here:
I assume you're wanting to know if the class under test reacts the right way when the CollectionChanged event is fired? If that's the case, you can do it something like this:
var project = MockRepository.GenerateMock<Project, INotifyPropertyChanged>();
project.Expect(p => p.SomeMethod())
.Repeat.Any()
.Raise(p => ((INotifyCollectionChanged)p).CollectionChanged += null,p,new NotifyCollectionChangedEventArgs());