using Dll in WinForm - winforms

I am trying to use DLL NI4882 in winForm.
There is namespace in dll "NationalInstruments.NI4882.Internal;" where a class exists "GpidDll" which is internal and sealed class.
This is the code snippet of class "GpidDll" in NI4882 DLL
[SuppressUnmanagedCodeSecurity]
internal sealed class GpibDll
{
[DllImport("ni4882.dll", EntryPoint="ibfind",CallingConvention=CallingConvention.StdCall)]
private static extern IntPtr _ibfind(string udname);
public static GpibHandle ibfind(string udname);
}
Now I want to call ibfind from winform. But I am getting error of "Unable to find an entry point" when I use
[DllImport(#"C:\Project\NationalInstruments.NI4882.dll",
EntryPoint="ibfind",CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr _ibfind(string udname);
calling function
public void ibfind_Ext(string udname, ref IntPtr ud)
{
ud = _ibfind(udname);
}
I also think of other option like creating object of GpidDll and then calling ibfind but I can't to that because of access specifier(Internal) as my project is in different namespace.

Related

Stubborn IntelliSense keeps flagging false "function X cannot be called with the given argument list"

Environment
Visual Studio 2013 and C++/CLI.
The (ho/e)rror
I faced a situation of IntelliSense giving error on a compiler compliant row. Thus a false positive.
The error is the following:
IntelliSense: function "< full qualified method name >" cannot be
called with the given argument list argument types are: <
expected argument type > object type is: < object type >
What happened
I made a UserControl. There I declared a custom event with relative delegate. I created a form. In form constructor I alloc a my user control instance and try to attach a form method to the control custom event.
Compiler says everything is ok. IntelliSense tells me that event attachment mismatches types.
How to reproduce
I digged in the problem and created an essential context that should reproduce the problem:
Create a solution with two projects: FavaTest (as ClassLibrary) and FavaForm (as Console application...or whatever).
In FavaTest create a UserControl whose name is FavaClass and paste the following in FavaClass.h.
#pragma once
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
namespace FavaTest {
public ref class FavaClass : public System::Windows::Forms::UserControl
{
public:
FavaClass(void)
{
InitializeComponent();
}
// -- here defines very simple event --
delegate void FavaDelegate();
event FavaDelegate^ FavaEvent;
protected:
~FavaClass()
{
if (components)
{
delete components;
}
}
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->SuspendLayout();
//
// FavaClass
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->Name = L"FavaClass";
this->Size = System::Drawing::Size(249, 147);
this->ResumeLayout(false);
}
#pragma endregion
};
}
In project FavaForm create a Form whose name is LaForm and paste the following in LaForm.h
namespace FavaForm {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
public ref class LaForm : public System::Windows::Forms::Form
{
public:
LaForm(void)
{
InitializeComponent();
// here simply allocs a FavaClass object and try to attach to FavaEvent event
FavaTest::FavaClass ^item = gcnew FavaTest::FavaClass();
item->FavaEvent += gcnew FavaTest::FavaClass::FavaDelegate(this, &LaForm::onfava);
}
void onfava(){}
protected:
~LaForm()
{
if (components)
{
delete components;
}
}
private:
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->SuspendLayout();
//
// LaForm
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(368, 261);
this->Name = L"LaForm";
this->Text = L"LaForm";
this->ResumeLayout(false);
}
#pragma endregion
};
}
Build FavaTest
In FavaForm project common properties add a new reference to FavaTest in order to use its generated dll as a dependencie
Build solution.
Now, while the compiler heralds everything is fine, you should see that IntelliSense complains something on the event attachment row, with the following errore message:
IntelliSense: function "FavaTest::FavaClass::FavaEvent::add" cannot be called with the given argument list
argument types are:
(FavaTest::FavaClass::FavaDelegate ^)
object type is: FavaTest::FavaClass ^
Ready to run package
I packaged all this in a side-test-standalone-solution zip file in order to make it possibile to unzip and run, but unfortunately (IMHO also questionably) I cannot post it here dued to SE guidelines, so it's up to you to make the debug context according to the above.
The question
I could also be missing something, but I used several times this algorithm before and it worked perfectly, now I'm experiencing this on two different machines (VS2013 and VS2015). Does this error apply to you too? And what's wrong with IntelliSense? It is such a simple scenario that I can't imagine I'm the only one experiencing it. I found no clue on the Internet though.
Solved.
It came out that in order to avoid IntelliSense to get crazy, the delegate definition has to be out of the event parent class scope. So in my situation all I had to do to get things right (for IntelliSense) was to move delegate outside the class adding the public keyword, such as:
namespace FavaTest
{
public delegate void FavaDelegate(); // moved out of the class with "public"
public ref class FavaClass : public System::Windows::Forms::UserControl
{
public:
[...]
// -- here defines very simple event --
// delegate row away from here
event FavaDelegate^ FavaEvent;
[...]
}
}

wpf - best practice of registering a DelegateCommand to a CompositeCommand

iv'e got a CompositeCommand exposed globally in my startup project
public static class Commands
{
public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
}
in a ControlLibrary referenced by my startup project iv'e got a Control which has a DelegateCommand ,
each instance of this Control has to register it's Command with the globally exposed DiceRolledCommand.
what wold be the best practice of doing so :
here are 3 idea's of which the first 2 i don't like because they are a kinda of hack , where you take some programming component (dp) and alter it's use for your benefit , resulting in poor code and design .
1)
a regular decadency property of type CompositeCommand which will be set with DiceRolledCommand
and on it's CallBack register MyControl's DelegateCommand (OnDiceRolledCommand) .
public class MyControl : Control
{
public DelegateCommand<Tuple<int, int>> OnDiceRolledCommand { get; private set; }
public CompositeCommand GlobalDiceRolledCommand
{
get { return (CompositeCommand)GetValue(GlobalDiceRolledCommandProperty); }
set { SetValue(GlobalDiceRolledCommandProperty, value); }
}
public static readonly DependencyProperty GlobalDiceRolledCommandProperty =
DependencyProperty.Register("GlobalDiceRolledCommand", typeof(CompositeCommand), typeof(MyControl), new UIPropertyMetadata(null,GlobalDiceRolledCommandPropertyChanged));
private static void GlobalDiceRolledCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var myControl= d as MyControl ;
var compoisteCommand = e.NewValue as CompositeCommand;
compoisteCommand.RegisterCommand(myControl.OnDiceRolledCommand);
}
}
<local:MyControl GlobalDiceRolledCommand="{x:Static local:Commands.DiceRolledCommand}"/>
i don't like this approach since it's a kind of manipulation where a Dependency Property is used has a Complex logical setter .
2) i could also do the same as in (1) using a third party class with an attached property which will register the OnDiceRolledCommand in an attached property's CallBack
public static class Commands
{
public static readonly CompositeCommand DiceRolledCommand = new CompositeCommand();
public static ICommand GetRegisterToDiceRolledCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(RegisterToDiceRolledCommandProperty);
}
public static void SetRegisterToDiceRolledCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(RegisterToDiceRolledCommandProperty, value);
}
public static readonly DependencyProperty RegisterToDiceRolledCommandProperty =
DependencyProperty.RegisterAttached("RegisterToDiceRolledCommand", typeof(ICommand), typeof(Commands), new UIPropertyMetadata(null,OnRegisterToDiceRolledCommandProperty);
private static void OnRegisterToDiceRolledCommandProperty(DependencyObject d , DependencyPropertyChangedEventArgs e)
{
var commandToRegister = e.newValue as DelegateCommand;
DiceRolledCommand.RegisterCommand(commandToRegister );
}
}
<local:MyContorl local:Commands.RegisterToDiceRolledCommand="{Binding OnDiceRolledCommand , RelativeSource={RelativeSource Self}}"/>
i also don't like this approach for the same reason as 1 ..
3) passing the composite command as a parameter to constructor , this approach is better since it keeps
the initializing logic in the constructor where it should be , i just can't figure out how to pass
an argument to a contractor through XAML , i'm not sure if it's even possible .
public class MyControl : Control
{
public MyControl(CompositeCommand globalDiceRolledCommand)
{
.........
globalDiceRolledCommand.Register(OnDiceRolledCommand);
}
}
<local:MyControl ..... >
Some how pass parameters to contractor in order to create the element in XAML
</local:MyControl>
to summarize :
A) any thoughts about (1) and (2) .
B) thoughts of how to accomplish 3 , and if it seems like good design .
C) Any good pattern of accomplishing this scenario.
thanks in advance .
Whenever I use Global Commands like that they are usually defined in either an Infrastructure class library which every library can reference. Or they are defined in a consuming core library that each module could reference directly.
I wrote a lot of this up in a Code Project article
Part 2 here

Resolve region manager in wpf

I am trying to do this in a specflow step definition file, so that I can create an object of view model and make method calls to it.
But I get an error saying "Interface cannot be resolved: Microsoft.Practices.Prism.Regions.IRegionManager (resolution path: TestClass)". What is that I am doing wrong?
public class TestClass
{
private IRegionManager _RegionManager;
[ImportingConstructor]
public TestClass(IRegionManger regionManager)
{
this._RegionManager = regionManager;
// stuff here
}
}
Are you expecting your test class to be instantiated by SpecFlow or via Prism? As both have dependency injection functionality.
So I wouldn't expect your test definition file to have any importing constructors or similar MEF attributes. Instead I would expect your test class to written more like
[Binding]
public class TestClass
{
[Given("I setup Prism")]
public void GivenISetupPrism()
{
// Call into prism
}
}
See the documentation on http://specflow.org for more details.

Ninject ActivationException in WinForms application

I am working on a project to implement DI (using Ninject) into an existing WinForms application, however I have hit a few issues and my knowledge of working with DI in WinForms is limited at best, however I have successfully used it several times in MVC projects.
I get this message when trying to create a form that has a constructor that requires an interface of a repository:
Error activating IProductionRepository
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IProductionRepository into parameter
productionRepository of constructor of type Main
1) Request for Main
I have searched on the web, but most of the articles I have read on this error either a dealing with much more complicated setups or are regarding parameter injection, which I am not sure is the issue here.
I have a form that is to launch the form that is to use DI (the error occurs on the kernel.Get call:
Private Sub txt_Click(sender As System.Object, e As System.EventArgs) Handles txt.Click
Try
Dim kernel As Ninject.IKernel =
New Ninject.StandardKernel(New NinjectFactory())
Dim form As Main = kernel.Get(Of Main)()
form.ConnectionString = App.pstrConnectString
form.ShowDialog(Me)
Catch ex As Exception
Support.ErrorHandler.ReportError(ex.Message, ex, True)
End Try
End Sub
I have my NinjectFactory with the correct binding (and several other commented out attempts):
public class NinjectFactory : NinjectModule
{
private IKernel _ninjectKernel;
public NinjectFactory()
{
_ninjectKernel = new StandardKernel();
}
public override void Load()
{
//_ninjectKernel.Bind(typeof(IRepository<>))
// .To(typeof(GenericRepository<>));
//_ninjectKernel.Bind(typeof(IProductionRepository))
// .To(typeof(ProductionRepository));
_ninjectKernel.Bind<IProductionRepository>().To<ProductionRepository>();
}
}
Finally I have the form I am trying to launch:
private IProductionRepository _productionRepository;
public string ConnectionString
{
get
{
return _connectionString;
}
set
{
_connectionString = value;
}
[Inject]
public Main(IProductionRepository productionRepository) : this()
{
this._productionRepository = productionRepository;
}
public Main()
{
InitializeComponent();
}
This is how I have used Ninject in MVC projects before and I haven't had an issue, however obviously there is something different regarding WinForms.
Any help would be greatly appreciated.
I suggest to use single point of dependency resolution, know as Composition Root, suggested by Mark Seemann (#mark-seemann) in his great book Dependency Injection in .NET. Your CompositionRoot might look like this:
public class CompositionRoot
{
private static IKernel _ninjectKernel;
public static void Wire(INinjectModule module)
{
_ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return _ninjectKernel.Get<T>();
}
}
public class ApplicationModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRepository<>)).To(typeof(GenericRepository<>));
}
}
You can wire them in Program
CompositionRoot.Wire(new ApplicationModule());
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(CompositionRoot.Resolve<Form1>());
Now your button handler could look like this:
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(_productionRepository.ToString());
}
Note: if you want to test your application with different dependencies, which is probably the case, then you create another module with different wiring configuration. In tests you will have another wiring logic with stubs and mocks.
I also don't like NInject attributes on my model and if you use constructor injection - you can get rid of them. My entities are simple POCOs.
public interface IProductionRepository
{
}
public class ProductionRepository : IProductionRepository
{
public override string ToString()
{
return "Foo";
}
}
Mark also makes a great case for WinForms with DI pattern and how it can be implemented, i really suggest his book.

How to use singleton over multiple assemblies in design time

I have 3 assemblies:
MyApp.Views (uses MyApp.Data and MyApp.Metadata)
MyApp.Data (uses MyApp.Metadata)
MyApp.Metadata
I have an interface, say IMetadata. Then, I also have an implementation in MyApp.Metadata which I register in a singleton class:
IoCContainer.Instance.Register<IMetadata, Metadata>();
Then, in design time, I use an assembly that needs to use the metadata (but it's the MyApp.Data that resolves the type):
IoCContainer.Instance.ResolveType<IMetadata>();
But this fails. The IoCContainer.Instance does not contain the same interfaces (actually, it's empty). The singleton implementation is really basic:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
public static IoCContainer Instance { get; private set; }
}
Somehow, it looks like separate assemblies are loaded in separate app domains (or something like that). Anyone knows a solution for this?
Could be a threading issue. Your singleton instance could be instantiated twice by different threads. Have a look at http://www.yoda.arachsys.com/csharp/singleton.html. It explains it in more detail and provides you with a thread safe solution.
Ok, problem seems to be solved. It might have 2 causes:
First, sometimes visual studio "updates" your references to shared libraries so one points to the bin\debug\mysharedassembly.dll, and the other one still points to ....\lib\mysharedassembly. This is some kind of stupid behavior of VS2010 where it tries to outthink the developer.
Second, I had this definition of the IoC Container:
public class IoCContainer
{
static IoCContainer()
{
Instance = new IoCContainer();
}
private IoCContainer()
{
}
public static IoCContainer Instance { get; private set; }
}
Which I changed to:
public class IoCContainer
{
private static readonly IoCContainer _instance = new IoCContainer;
private IoCContainer()
{
}
public static IoCContainer Instance { get { return _instance; } }
}
Anyway, problem solved :)

Resources