How do I make my library work with using-directive? - c#

I created a class library with .Net 6.0 which looks like this:
namespace MyLib
{
public static class MyLib {
public static void someFunction() { }
}
}
I created a nuget package and added that package to another application. My expectation was that I would put using MyLib at the top of a class and then could call MyLib.someFunction() in the code. But instead, I always have to call MyLib.MyLib.someFunction(), with the using-directive doing nothing.
Can someone explain to me what I'm doing wrong?

Related

How to call a class inside of an application - C#

I have created a console application that creates CSV data when it is run. I want to move this app to another project as a class, and then call that class when a button is pressed. How would I do this?
The class I will move looks like this
namespace ConsoleApp3
{
class Program
{
static void Main()
//content
}
public class MyClass
//more content
}
and the button would look like this
//form data
<a class="button">Download CSV</a>
My controller has simple actions...
public IActionResult Index(){
return View();
}
public IActionResult DownloadCSV(){
//do I need something here?
return View();
}
A good option is to create this class as a library
-like this: Build a C# Standard library
Once your new library is created you need to Reference it from the other project where you want to use this class
Creating a class as a library will let you use it in any other project/application in the future.
So I would strongly recommend to keep your repetitive classes as libraries, such as CSVManager class or ConnectionManager class and any other class you might use more than once.

Is there a cleaner method of making COM visible applications?

Given a specific class:
public class Klass
{
public int value;
public void doSomething(){
return;
}
}
To make said class COM visible, as far as I know, one needs to do a few things:
Import System.Runtime.InteropServices
Create an interface for the class.
Extend the interface created.
Create 2 unique GUIDs, one for the Interface and another for the class.
Add Dispatch IDs to the interface.
Producing something like:
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IKlass
{
[DispId(0)]
public int value;
[DispId(1)]
public void doSomething();
}
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
ClassInterface(ClassInterfaceType.None)]
public class Klass : IKlass
{
public int value;
public void doSomething(){
return;
}
}
The resulting code looks utterly gross in my opinion... The question is, is there a simple cleaner method of creating these COM interfaces? I can imagine modifying the build process myself to give a interop feature. E.G.
public interop class Klass
{
public interop int value;
//...
}
However, this is non-standard, which has it's issues as well. Is there anything built-in to Visual Studio / C# that I can use to make building COM interfaces easier/cleaner?
As suggested by Zohar Peled the best way is to use RegAsm.exe:
Create some C# class library "TestProject":
using System.Windows.Forms;
namespace TestProject
{
// Note. Only public classes are exported to COM!
public class Test
{
// Note. Only public methods are exported to COM!
public void testIt() {
MessageBox.Show("Yellow world");
}
}
}
IMPORTANT:
Only public classes are exported to COM. And only public methods of these classes are available via a COM object instance.
Sign the project.
In AssemblyInfo.cs set [assembly: ComVisible(false)] to [assembly: ComVisible(true)]. Note: You can also use attribute [ComVisible(true)] before each class you want to expose to COM. This just sets the default to true making it easier to work with if building an API
Build the project.
Run regasm. Remember to use the correct version of Regasm (32-bit/64-bit) and the version for your .NET framework:
# .NET v4.5 64-bit
"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" -tlb -codebase "C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.dll" -verbose
# .NET v4.5 32-bit
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" -tlb -codebase "C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.dll" -verbose
...
Regasm should output something like this:
Microsoft .NET Framework Assembly Registration Utility version 4.7.3056.0
for Microsoft .NET Framework version 4.7.3056.0
Copyright (C) Microsoft Corporation. All rights reserved.
Types registered successfully
Type 'TestProject.Test' exported.
Assembly exported to 'C:\Users\sancarn\Desktop\tbd\TestProject\TestProject\bin\Debug\TestProject.tlb', and the type library was registered successfully
Now you can test the file in VBScript for example:
Dim o As Object
Set o = CreateObject("TestProject.Test")
Call o.testIt
Sancarn answers your question, but note that this makes ALL COM-compatible classes in your project COM-visible as well, which you might not want (see here and here). If you do not explicitly set the UUIDs you are opening yourself up to problems when you deploy if you access the classes with early-bound clients like VB or VBA (not VBScript, which is late-bound).
Yes it's not "clean" but neither is COM, especially when you want to expose it to late-binding clients live VBScript.
I would also change your public field to a property, which is more standard for public members:
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
public interface IKlass
{
[DispId(0)]
public int value {get; set;}
[DispId(1)]
public void doSomething();
}

How do I use the AppGlideModule in Xamarin.Android?

Using the Glide library on Xamarin.Android, I was hoping someone could shed some light on how to use the AppGlideModule. According to the documentation, I need to register my custom ModelLoader using the AppGlideModule.
Here is a link to the example in the Glide documentation:
http://bumptech.github.io/glide/tut/custom-modelloader.html#writing-the-modelloader
Here is my custom AppGlideModule class:
public class MyCustomGlideModule : AppGlideModule
{
public override void ApplyOptions(Context context, GlideBuilder builder)
{
base.ApplyOptions(context, builder);
}
public override void RegisterComponents(Context context, Glide glide, Registry registry)
{
registry.Prepend(
Java.Lang.Class.FromType(typeof(Java.IO.OutputStream)),
Java.Lang.Class.FromType(typeof(Drawable)),
new MyCustomImageStreamModelLoaderFactory()
);
}
}
I don't know if it's necessary, but if you'd like to see the classes I made for the ModelLoader, please let me know in the comments.
Old question but here is the trick. You will need to create an Android/Java library that contains an AppGlideModule wrapper. This library contains nothing else and is simply used to generate the GlideApp class. It needs to contain a static instance of your final AppGlideModule. Basically, it will look like this :
#GlideModule
public class XamarinGlideModule extends AppGlideModule {
public static AppGlideModule InjectedModule;
#Override
public void registerComponents(Context context, Glide glide, Registry registry) {
if(InjectedModule != null) {
InjectedModule.registerComponents(context, glide, registry);
}
}
}
You will then need to wrap this library in an Android binding library. Nothing is worthy of mention in this step, simply drop your built AAR in the binding project, add the matching version of the Glide Nuget and build.
You can then add a reference to that binding library in your app project. In your Android Application class, you will need to setup the InjectedModule static property to inject your Xamarin implementation. You must do this before any call to Glide, something similar to this :
public override void OnCreate()
{
base.OnCreate();
XamarinGlideModule.InjectedModule = new MyLoaderModule();
var temp = GlideApp.Get(this); // Init Glide, it will register your Xamarin module
}
Now there's one more option to use custom glide module from C# code. Just install package of this project:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.AppModuleInjector
NOTE: if you need custom AppModule for glide just to accept self-signed certificates, you can install this package as well, it already has implementation of such module:
https://github.com/KDD-Digital-Healthcare-GmbH/Kdd.Glide.UnsafeUrlLoadingAppGlideModule

Change namespace on dynamic loading of assembly

I have an app which uses a specific type in a separated dll (developed by someone else).
Say it is InnerType :
namespace SeparatedAssembly
{
public class InnerType
{
}
}
Until now, I was referencing a version of this dll in Visual Studio and I was using the InnerType in my app. However, since the code inside the InnerType could change, the assembly is loaded at runtime with the "AssemblyResolve" event.
But now, the namespace of this class has changed :
namespace SeparatedAssembly.Inner
{
public class InnerType
{
}
}
So, I have an exception TypeLoadException because my app can't find this type anymore. I can't just reference this new version and change the namespace I use, because it as to be compatible with the old versions of this dll.
So my question is: is it even possible to specify the namespace to look for in an assembly, in the AssemblyResolve event?
If there is a way to catch this exception and try with a different namespace, it's also OK.
Thanks.
No, the full name of the method to be called is specified in the calling assembly, and you can't "rewrite" it in an easy way. The namespace is part of the name. I'll make a reference to another response I gave some time ago: Is C# namespace compiled into IL files to be “complete” names?.
To give an example in TryRoslyn:
namespace Foo
{
public class Bar
{
public void Zoo()
{
Console.WriteLine("Hello");
}
}
}
is translated to
.class public auto ansi beforefieldinit Foo.Bar
extends [mscorlib]System.Object
{
(the namespace Foo is directly part of the name Foo.Bar)
and then the method call to Console.WriteLine is:
call void [mscorlib]System.Console::WriteLine(string)

.NET substitute dependent assemblies without recompiling?

I have a question about how the .NET framework (2.0) resolves dependent assemblies.
We're currently involved in a bit of a rewrite of a large ASP.NET application and various satellite executables. There are also some nagging problems with our foundation classes that we developed a new API to solve. So far this is a normal, albeit wide-reaching, update.
Our heirarchy is:
ASP.NET (aspx)
business logic (DLLs)
foundation classes (DLLs)
So ASP.NET doesn't throw a fit, some of the DLLs (specifically the foundation classes) have a redirection layer that contains the old namespaces/functions and forwards them to the new API. When we replaced the DLLs, ASP.NET picked them up fine (probably because it triggered a recompile).
Precompiled applications don't though, even though the same namespaces and classes are in both sets of DLLs. Even when the file is renamed, it complains about the assemblyname attribute being different (which it has to be by necessity). I know you can redirect to differnet versions of the same assembly, but is there any way to direct to a completely different assembly?
The alternatives are to recompile the applications (don't really want to because the applications themselves haven't changed) or recompile the old foundation DLL with stubs refering to the new foundation DLL (the new dummy DLL is file system clutter).
You want to move the types to a new assembly? You can do that with [TypeForwardedTo(..)].
If you originally have (AssemblyA):
namespace SomeNamespace {
public class SomeType {}
}
You can instead move that type into AssemblyB, and have a virtually empty AssemblyA which references AssemblyB and simply contains:
[assembly: TypeForwardedTo(typeof(SomeNamespace.SomeType))]
Then anything trying to load SomeNamespace.SomeType from AssemblyA actually gets the type from AssemblyB.
Most of the runtime respects this attribute... everything except WCF extensions. Which bit me ;-p Oh, and it isn't a fan of nested types...
//File: RKAPPLET.EXE
namespace RKAPPLET
{
using RKMFC;
public static class Program
{
public static void Main ()
{
RKMFC.API.DoSomething();
}
}
}
//File: RKMFC.DLL
namespace RKMFC
{
public static class API
{
public static void DoSomething ()
{
System.Windows.Forms.MessageBox.Show("MFC!")
}
}
}
//File: RKNET.DLL
namespace RKNET
{
public static class API
{
public static void DoSomethingElse ()
{
System.Windows.Forms.MessageBox.Show("NET!")
}
}
}
namespace RKMFC
{
public static class API
{
public static void DoSomething ()
{
RKNET.API.DoSomethingElse()
}
}
}
I want RKAPPLET.EXE, compiled with RKMFC.DLL, to find RKNET.DLL (which has a copy of everything in RKMFC.DLL and then some) without recompiling either RKAPPLET.EXE (to point to it) or RKMFC.DLL (to redirect types).
Did you try adding <assemblyBinding> setting to config file ?
http://msdn.microsoft.com/en-us/library/twy1dw1e.aspx

Categories

Resources