MAF with class inside DLL passing to host - c#

I'm developing a MAF application which, in a DLL contains a class. The problem is, when one of the methods exposed by one of the AddIns uses this class. Example:
class A
{
Property_1
Property_2
Method_X()
}
And my AddIn has a method which use class A
MyAddIn.Set(class A);
So, with this, where must I place the DLL in the pipeline? Or how should I proceed with this scenario?
When the proyect start, the warnings of the AddInStore.Update() method throws messages like: unable to connect a part of a canalization...
So, there is an article this which says "There are many other capabilities MAF provides such as versioning, passing collections and WPF visuals, passing non-serializable types, etc.". But I can't find an example.
EDIT:
Thanks to Panos for this link about the restrictions on contracts. And after more research I've found this article which, through the Paint.NET proyect, shows how to use data types in the host without referencing.
After reading both sources, I know that this is what I'm looking for. But I can't understand it yet.
As a final petition, can someone please provide me code example? Just to finally get it.
Thanks.

You should study these guidelines on what types are allowed in the contracts assembly.
Basically you should not reference the dll you mention in the pipeline (contracts, adapters and views) because this way you can leak types from the host to the add-in. This means that you will lose versioning because all pipeline segments are referencing the same assembly. What this means is that if the add-in is referencing v.1 of the assembly and the contract is referencing v.2, both versions will be loaded and an InvalidCasrtException will be thrown.
A solution to this is to create an interface based on class A and make it a contract. Then your add-in can provide the implementation. Thiw way you will not lose versioning.
Regards,
Panos

Related

How to hide C# class from custom IL Inspector?

I am currently working with a piece of software known as Kofax TotalAgility or KTA for short.
This is Business Process Automation Software, which I have the "pleasure" of expanding with custom .net libraries.
I have been creating a MS Graph library to perform actions with the MS Graph API. The API works great and I am quite pleased with how it turned out.
However due to the way KTA is accessing methods in classes I have used "Data classes" (dont know if that is the right word) to use as input parameters for my methods. To be clear these methods have no functionality other than to store data for methods to use, the reason I am doing this, is because of the way it is structured in the KTA class inspector (I am assuming that KTA uses the IL Code from my library to create a list of classes and methods).
This is what I am expecting the user is shown when they are using my methods. As you can see by using classes as input parameters I get this nice hierarchical structure.
By using classes as input parameters another issue occurs which is that my "Data Classes" are show in the list of classes, which produces alot of unnecessary clutter.
Is there a way to hide these classes from the inspector? I get that it might be an internal KTA issue, which of course would mean I am not asking in the right place, and it is an internal Kofax issue.
However if there is some C# or .NET way of doing this, that would be preferable.
There are a number of different terms for the data/parameter classes that you mention, such as DTO (data transfer objects), POCO (plain old C# objects), or the one that you can see in the KTA product dlls: model classes.
There is not a direct way to hide public classes from KTA. However, when you use the KTA API via the TotalAgility.Sdk.dll, you notice that you don’t see all of the parameter classes mixed in with the list of the classes that hold the SDK functions. The reason is just that these objects are in a separate referenced assembly: Agility.Sdk.Model.dll. When you are configuring a .NET activity/action in KTA, it will only list the classes directly in the assembly that you specify, not referenced assemblies.
If you are using local assembly references in KTA, then this should work because you can just have your referenced assembly in the same folder as your main dll. However if you are ILMerging into a single dll to can add it to the .NET assembly store, then this approach won’t work.
When ILMerged together, the best you can do is to have your parameter classes grouped in a namespace that helps make it clear. What I do is have a main project with just one class that acts as a wrapper for any functions I want to expose. Then use ILMerge with the internalize option, which changes visibility to internal for any types not in the primary assembly. To allow the model classes to still be public, I keep them in a specific namespace and add that namespace to the exclude list for the internalize command. See Internalizing Assemblies with ILMerge for more detail.
Keep in mind that anyone seeing this list is configuring a function call with your dll. Even if they are not a skilled developer, they should at least have some competence for this type of task (hopefully). So even if the list shows a bunch of model classes, it shouldn’t be too hard to follow instructions if you tell them which class is to be used.

Ensure only one class can access a reference dll?

I have a project where I want only one class to have access to a dll. I would be content with hiding the dll from intellisense, but still having access to it if that is an option. Either way, I want only one class to use the dll and for it not to be seen and/or accessible otherwise.
I'm using C# in visual studios.
Simply said: You can't do that (but keep reading).
Basically, a DLL (From the .NET perspective) is a bunch of code and config files. No more than that. So, given that you'll need to make public those classes in order to be used from another ones outside that assembly then you can not.
What you can do (I ended up doing this a few years ago) is to use some kind of reflection to determine which class (and namespace) is trying to access your assembly and only permit the proper one.
Other way is to implement a key negotiation between your DLL and the permitted assembly. You'll need to implement those manually, as far as I know.
Anyway, keep in mind there's always a way to bypass this kind of protection by disassembling and modifying your code. So, at least, don't forget to obfuscate the file. Anyway, this will just make it a little more painful, but still possible.
An alternate approach, if you goal is to stop people using the functionality of the dll by accident is to push your wrapper class into an intermediary assembly. Your project then references that intermediary project, rather than the underlying dll which effectively hides it. So your project structure would change to something like this:
Main Project -> references API Wrapper Project -> references API DLL
For this to work, your wrapper project needs to make sure that it doesn't accidentally expose any of the API DLL classes through its public interface.
Obviously this doesn't stop your developers from going in and adding a reference to the API DLL so that they can use the library directly, but if the goal is to stop accidental access to the API DLL classes because intellisense has helped the developer out a bit too much then it might be a viable option.

Winform application program interface "Argument type is not assignable to parameter type"

I have a Winform application where I would like to implement some sort of an interface for the customer, so parts of the code is changeable by customer later on if they need to. I believe my approach is wrong, because I get an error in Visual Studio after recompiling my Winform application. The error is "Argument type MyClass is not assignable to parameter type MyClass", but I'm still able to recompile it. I'm worried this would break later on...
This is how I have implemented it until now:
In my winform application I have created an abstract class with a virtual method.
I'm "releasing" an open source project dll assembly for the customer where this abstract class is implemented and the method is calling the base method in the abstract class. If customer would like to change the method, they simply implement it themselves.
This open source project is then referenced and implemented in my winform application.
When customer would like to change the method they implement the method, recompile the dll and replace the new dll with the one I distributed with my assembly.
My winform application has it's own strong name, and the open source project has it's own strong name.
However, when I recompile my Winform application after having referenced the open source project, i get this error: "Argument type MyClass is not assignable to parameter type MyClass". I can still recompile the project. But I'm concerned the implementation has some serious flaws and will break later on. Especially also since I have implemented WyBuild where I will distribute updates for the Winform application.
I need to provide a way for the customer to change some methods in the application without having access to all the source code. How can this be achieved if my implementation is wrong, what is your suggestion?
Thanks.
I'd say that approach itself is a bad way to do it. To me, this sound very error prone, and you state yourself that you have a bad feeling about it. If so, then really don't do it this way.
There sure is a couple of other solution thinkable, but given your descriptions I might do it as follows, which would stay your your original intention.
Have a look at Microsoft's Managed Extensibility Framework (MEF), which could help you in several ways.
Simply put, it would work like this:
You define the interface that the custumer has to implement.
The client then creates an assembly that implements exactly that interface and puts it a location that is monitored by MEF
MEF loads the assembly automatically (no need to reinvent the wheel)
MEF gives you a lot of control over how you want it to work. Like, like should it allow loading only or multiple assemblies that implement that interface at the same time, or should only look for plugins only at the start of the application or monitor the plugin location during the full life-time of it.
Also by doing it this way you get rid of the custom solution you are assembling here and instead use a mature framework that provides a standadized way to do it. Just have look at some tutorials on the net, it is really easy to get into.

In C#, how to restrict who can call a method at compile time

In C#, is it possible to restrict who can call a method at compile time?
I've looked into directives, but that didn't work since I can't assign values to symbols.
#define WHO VisualStudioUser.Current // does not work
I also looked into Code Access Security (CAS) but that's runtime enforcement, not compile time.
The requirement is to restrict access to a method at compile time for specific developers given the method exists in a pre-compiled assembly.
here's more details...
I'm building a framework or a series or assemblies for a team of developers. Because of our software license restrictions, I can only allow a few developers to write code to make a call to some restricted methods. The developers will not have access to the source code of the framework but they'll have access to the compiled framework assemblies.
The quick answer will be: No this isn't possible, and if you need to do it, you're Doing It Wrong.
How would this even work? Does it depend who who's running the code or who wrote it?
Edit There's kind of a way using InternalsVisibleTo and restricting accessing in source control to the assemblies that InternalsVisibleTo is specified for. See Jordão's answer
The requirement is to restrict access to a method at compile time for specific developers given the method exists in a pre-compiled assembly.
One way is to mark the method private or internal, it won't be callable by anyone outside the assembly. UPDATE: Also take a look at the InternalsVisibleTo attribute, which is used to define which assemblies can "see" internals of your assembly.
Another way is to divide the code you want to distribute from the code you don't want people to call into separate assemblies. Maybe you just share an assembly mostly of interfaces with your users, that they them compile against; and you have a separate assembly with implementations that they shouldn't reference directly. Your internal team would have access to the implementation assembly. This is just a common form of dependency management, the dependency inversion principle.
Draft:
Compile the restricted code into (obfuscated) DLLs: TypeA.dll, TypeB.dll etc.
Define an interface for each type, and compile them into separate DLLs: ITypeA.dll, ITypeB.dll etc.
Create a "guard assembly", and embed all restricted assemblies into it: Guard.dll. This has a ResolveEventHandler, and methods to instantiate different types defined in the embedded restricted DLLs. Instances are returned through their interface.
Developers get the interface DLLs and the Guard.dll. Each developer can get a Guard.dll with special authentication tokens in it. For example, a Guard.dll can be bound to PC, an IP address, a GUID issued to the developer, anything.
The developer can instantiate those types for which she has the proper authentication code, and uses the object instance through an interface.
Sorry this is a bit fuzzy, because it was more than a year ago when I used these techniques. I hope the main idea is clear.
Can you try using Extensible C# developed by ResolveCorp, some of the links for study and implementation are:
http://zef.me/782/extensible-c
http://www.codeproject.com/KB/architecture/DbCwithXCSharp.aspx
http://weblogs.asp.net/nunitaddin/archive/2003/02/14/2412.aspx
http://www.devx.com/dotnet/Article/11579/0/page/5

Flexible reporting system with dynamically loaded assemblies

I want to build a flexible reporting system for my application. So far I only have a concept in my head and need some tips on implementation. I'm using Crystal Reports to render reports and I know how to load reports dynamically.
Now, the idea is that every report will be packaged as a separate assembly (.dll). The reporting framework will be loading every custom report and communicating with it via clearly defined interface like this:
public interface IReport
{
string GetTitle();
string GetDescription();
void SetParameter();
void Print();
}
Also, there will be some base implementation (as an abstract class) that will handle some common operations on the reports (like binding to data source, etc.):
public abstract class Report
{
...
}
Inside every dll there will be an implementation of concrete class, representing this or that report:
public class CustomersReport : Report
{
...
}
Now, I have to figure out the following:
1) How to dynamically locate and load the dll?
2) How to create an instance of concrete class (CustomerReport) and cast it to IReport in order to call necessary methods on it?
Have you ever implemented such an extensible system? Could you please share your expertise / code snippets?
Thanks in advance.
EDIT:
While investigating this question I found Jon Skeet's article on Plug-ins and Cast Exceptions that might be helpful.
See this:
Problem with dynamic loading of a dll into my program
Is doing exactly what you want wihtout all the YAGNI around it.
Have a look at Mono.Addins (it's MIT license so it's ok with closed software). From your description it does what you need. Basically it uses a dependency tree + plugins based on interfaces. It has it's own manager for loaded .dll-s and its objects are based on the loaded interface, so you don't need any more magic casting to call anything.
You can consider MEF from Microsoft. It is a composition engine that can be set up to monitor a local folder and automatically load assemblies that export parts (implementation of IReport in your case) that you're interested in.
We do have a system like that we implemented sometime ago. We have a single assembly with reports that we load into a separate application domain and reload if the file version has changed. Then we use .NET remoting to communicate between app domains. We considered using Add-in framework from Microsoft but we found it to be very complex and imposing and decided it was too heavy and complex in our case.

Categories