C# DLL does not expose methods - c#

I am working with a C# project that I did not create. I stripped it down very much.
I thought I did everything correctly. It compiles fine, and I can reference the DLL in e. g. a VB.NET application and use it.
However, the DLL's methods are not exposed.
Can somebody tell me if he seems something wrong immediately?
This is the important part of the DLL, I think:
using System;
using System.Collections;
using System.Data;
using System.Reflection;
using System.Text;
using SevenZip.Compression.LZMA;
namespace SevenZipControl
{
public static class Zipper
{
public static bool compressBytes(byte[] InputBytes,out byte[] OutputBytes)
{
OutputBytes=SevenZipHelper.Compress(InputBytes);
return true;
}
public static bool decompressBytes(byte[] InputBytes, out byte[] OutputBytes)
{
OutputBytes = SevenZipHelper.Decompress(InputBytes);
return true;
}
}
}
This is how I would use it in VB.NET:
Dim c As SevenZipControl.Zipper
c. (...)
But my functions "compressBytes" and "decompressBytes" are not available as one can see in this screenshot:

Your code lists static methods. You are creating an instance of the SevenZipControl.Zipper class.

To piggyback on #JAnderson's answer, you shouldn't need to instantiate with Dim. The following should work:
SevenZipControl.Zipper.compressBytes(data)
For some info on how the notion of static classes translates into VB, see this discussion

Related

How to use IEnumerable<T> in a class constructor parameter

I am trying to make some code in my MVC controller (export to Excel) more generic, as I've reached the point where I'm typing out almost identical code in multiple controllers. To make the export to Excel function so that exists in only one place -- rather than in many places -- I had the idea of using a generic IEnumerable so I could feed any IEnumerable into the class. (See code block below.)
I know that I can use byte[] as a parameter (and I might still use that as an other constructor choice), but it would be nice if I could use an IEnumerable in this instance.
However, Intellisense immediately tells me that "the type or namespace T could not be found".
Is is possible to use IEnumerable<T> for this purpose?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebApplication1.CentralFunctions
{
public class ExportToExcel
{
ExportToExcel(IEnumerable<T> inputCollection)
{
// TODO: place my "export to excel" commands here.
}
}
}
You need to define what T represents to the compiler somewhere. Since you are dealing with a class constructor, you need to make the class generic in order to define T.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebApplication1.CentralFunctions
{
public class ExportToExcel<T>
{
ExportToExcel(IEnumerable<T> inputCollection)
{
// TODO: place my "export to excel" commands here.
}
}
}
The T type is «unknown», i.e. not specified.
It seems you want to make the ExportToExcel class generic, and the T seems to be a type parameter:
public class ExportToExcel<T>
{
ExportToExcel(IEnumerable<T> inputCollection)
{
// ...
}
}
You need to declare your T type at class level, If you want you can also add a constraint to T
public class ExportToExcel<T>
{
ExportToExcel(IEnumerable<T> inputCollection)
{
// TODO: place my "export to excel" commands here.
}
}
I have accepted #NightOwl888 as the best answer. Thank you to #Sergei and #Luke for also answering.
Their answers helped me to write the class constructor correctly and now I can greatly simplify my code. I am sharing this because it explains the full context of the question and demonstrates how I can place it into my MVC system. This is the "hello world" version and can serve to help others like me who are figuring out how to get started.
Now I can simplify the controller action to this:
View:
<p>#Html.ActionLink("Export to Excel","ExportToExcel")</p>
Controller Action:
public ActionResult ExportToExcel()
{
IEnumerable<TroveLog> data = db.TroveLogs.AsEnumerable();
var export = new ExportToExcel<TroveLog>(data);
return RedirectToAction("Index");
}
And this is where I can place the single block of code that can export any IEnumerable to Excel. When I use Debug mode (F5), I can see the Debug.WriteLine results and verify that I am seeing the correct information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
namespace WebApplication1.CentralFunctions
{
public class ExportToExcel<T>
{
private IEnumerable<T> data;
public ExportToExcel(IEnumerable<T> inputCollection)
{
this.data = inputCollection;
// Run in Debug Mode (F5) and see results when clicking ActionLink.
Debug.WriteLine("Object: {0}", data.GetType());
Debug.WriteLine("RowCount: {0}", data.Count());
// TODO: place my "export to excel" commands here.
}
}
}

Create and Using DLL in same Project in c#

I am having a DLL file. With the use of DLL, I have to call the methods and add some more methods in my project. Now, I need to migrate the older DLL to Make that project as a new DLL. I done this But the problem is The C# code is converted to net module it shows two errors. I am not clear about that. kindly help me over it.
DLL Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace mcMath
{
public class mcMathComp
{
private bool bTest = false;
public mcMathComp()
{
// TODO: Add constructor logic here
}
/// <summary>
/// //This is a test method
/// </summary>
public void mcTestMethod()
{ }
public long Add(long val1, long val2)
{
return val1 - val2;
}
/// <summary>
/// //This is a test property
/// </summary>
public bool Extra
{
get
{
return bTest;
}
set
{
bTest = Extra;
}
}
}
}
CS Project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mcMath;
namespace mcClient
{
class Program
{
static void Main(string[] args)
{
mcMathComp cls = new mcMathComp();
long lRes = cls.Add(23, 40);
cls.Extra = false;
Console.WriteLine(lRes.ToString());
Console.ReadKey();
}
}
}
Errors:
Program.cs(5,7): error CS0246: The type or namespace name 'mcMath' could >not be found (are you missing a using directive or an assembly reference?)
Tried Methods:
I will add the reference via Project-> Add Reference.
The using Reference also used.
Put the DLL into the current project debug/release folder
I'm guessing you used to have the code side by side, i.e.
public int Add(int a, int b)
{
return a + b;
}
public void SomeMethod()
{
var result = Add(2,3);
}
This works because the scope (this.) is applied implicitly, and takes you to the Add method on the current instance. However, if you move the method out, the scope is no longer implicit.
You will need one of:
the type name if it is a static method
or a static using if using C# 6
a reference to the instance if it is an instance method
Then you would use one of (respectively):
var result = YourType.Add(2,3); (plus using YourNamespace; at the top)
using static YourNamespace.YourType; at the top
var result = someObj.Add(2,3);
Checking the compiler message, it sounds like you've done something like (line 7):
using YourNamespace.YourType.Add;
which is simply wrong; you don't use using to bring methods into scope - only namespaces and (in C# 6) types.
Likewise, I suspect you have (line 22):
var result = YourNamespace.YourType.Add(x,y);
which is not valid as this is not a static method.
Create and Using DLL in same Project in c#
DLL or Class Library is a separate project that can be part of same solution.
As you already know, adding a reference to that dll/project will make it available in your app project.
However if function Add in dll is in different namespace (which would be normal) u would need to add using clause at the beginning of your class

Getting the size of a structure meant for memory mapping

The Question In a Nutshell:
How can I get the size of a user defined structure passed as an object to a class library?
Overview:
The point of this test project is to build a class library that wraps up memory sharing using memory mapping within .Net 4 (Or less). In the end I want to be able to define a structure in my main application, pass it to the class library wrapper and let the class library determine the size of the structure.
Definitions:
MyAppA: Main application, the one that will create the memory map
instance initially.
MyAppB: Second application used to communicate
with MyAppA. This will tap into the existing memory map.
MemoryMapTool: This will be the class library that wraps up all the memory sharing.
TestStruct: This will be the structure defined in MyAppA and MyAppB that will be the exact same in both applications but might change from time to time. MemoryMapTool would NOT know the structure layout at any time, it will simply see it as an object.
Initial Idea:
I want the class library wrapper to have no knowledge of the TestStruct generated by MyAppA other than it is an object that the class library wrapper needs to keep up with and use for memory sharing...
I was thinking I would create the TestStruct in MyAppA and add as many variables to it as I needed (in this case just 1, a string). Then pass it into the MemoryMapTool constructor and let the MemoryMapTool class determine the size of the struct. This is currently the issue. Working with memory I tend to be cautious and research before I just try something that will possibly fail killing my IDE or OS... ;)
I was originally going to just pass the TestStruct straight to the MemoryMapTool constructor but ran into this issue...
long lMapSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(oData));
Error: The type or namespace name 'oData' could not be found (are you missing a using directive or an assembly reference?)
I then was thinking of trying to just use...
long lMapSize = System.Runtime.InteropServices.Marshal.SizeOf(oData);
... and it seems to work (at least the IDE likes it). But for some reason I don't feel like that's the correct way to do it.
UPDATE: After trying that I get a new error...
Error: Type 'MyAppA.Form1+TestStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
Current Source
MemoryMapTool.cs Contents
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.MemoryMappedFiles;
using System.Threading;
namespace SharedMemoryWorker
{
public class MemoryMapTool : IDisposable
{
#region Private class variables
private string m_sLastError = "";
private MemoryMappedFile mmf = null;
private string m_sMapName = "";
private object m_oData = null;
#endregion
#region Public properties
public string MapName
{
get
{
return m_sMapName;
}
set
{
m_sMapName = value;
}
}
public object Data
{
get
{
return m_oData;
}
set
{
m_oData = value;
}
}
#endregion
#region Constructor
private MemoryMapTool(string sMapName, object oData)
{
long lMapSize = System.Runtime.InteropServices.Marshal.SizeOf(oData);
try
{
//Save the map name
m_sMapName = sMapName;
//Create new map or use an existing one
//mmf = MemoryMappedFile.CreateOrOpen(m_sMapName, lMapSize);
}
catch (Exception ex)
{
m_sLastError = ex.Message;
throw new NullReferenceException("Error creating new object!");
}
}
public void Dispose()
{
//Deconstructor
}
#endregion
#region Public class methods
public string GetLastError()
{
return m_sLastError;
}
#endregion
}
}
MyAppA, Form1.cs Contents
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyAppA
{
public partial class Form1 : Form
{
#region Public structures
public class TestStruct
{
#region Private class variables
private string m_sTest = null;
#endregion
#region Public properties
public string Test
{
get
{
return m_sTest;
}
set
{
m_sTest = value;
}
}
#endregion
}
#endregion
public Form1()
{
InitializeComponent();
}
}
}
MyAppB, Form1.cs Contents
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyAppB
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
I think the error is pretty clear. You need to tell the CLR how you want the structure or class members to be laid out in memory. See the StructLayoutAttribute - it needs to be applied explicitly to classes (whereas for structs Sequential is the default).
From your description it appears that you want to do IPC between two or more managed processes. You may also want to establish a unified marshaling strategy for strings (see the MarshalAsAttribute). You can choose one and stick with it throughout your classes.
Finally, I would like to say that this isn't really appropriate for what you're trying to do (too much overhead and room for error). Instead you could:
Still use MMFs but serialize your classes using binary serialization or even JSON.
Design a service oriented architecture based on either WCF or WebAPI (can be selfhosted now, via OWIN/Katana).
Ultimately you can use raw TCP/IP sockets as well and design a small protocol for your apps.
My choice would be #2. Performance can be very good, especially with WCF and on the same computer with named pipes or net.tcp bindings and it just works.

access a Form1 public function from static class inside Form1

When writing this post i was checking all questions asked with related subject
and couldent find a simple answer to this Newbs C# issue
i would like ... if i may , to have as much as it can be a well-explaind answer (Please!)
i made a public static class
public static class MyLoadedBtmpToolBox
{
public static string FnameToLoad;
public static bool PutLoadedByteArrInPicbox;
public static string[] LoadedRefrnce;
public static int SourceX_Loaded, SourceY_Loaded, RectWidth_Loaded, RectHeight_Loaded;
---> public static int tst = Str2Int(LoadedRef[0]);
public static byte[] LoadedByteArr;
}
this calss as usually does by default, is within the main form i am using
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Security.Cryptography;
using WindowsInput;
namespace MyScrCupTry1
{
public partial class MyForm1 : Form
{
public static class MyLoadedBtmpToolBox
{
public static int testStr2Int = Str2Int("100");
}
public int Str2Int(string STR)
{
int strInt = Convert.ToInt32(null);
if (isntEmpty(STR))
{
strInt = Convert.ToInt32(STR);
}
else
{
MessageBox.Show("theString " + STR + " is Null");
}
return strInt;
}
}
i can't assing the testStr2Int a value , by using my public "helper Method" Str2Int() from the main form
i am Getting Error :
Error 1 An object reference is required for the non-static field, method, or property 'MyScrCupTry1.MyForm1.Str2Int(string)' G:\RobDevI5-Raid-0\Documents\Visual Studio 2010\Projects\WindowsFormsApplication2\WindowsFormsApplication2\MyForm1.cs 95 45 MyScrCuptry1
What is the right way for accessing Main Form Public elemets from a static Class
if it is possible / (not illegal)...
ReEditing
after Those two answers ...
I tried to implement
the code from first answer without expected results i guess i didn't know the right code structure with override OnLoad(..) thing ...
BUT !
i have turnd the method Str2Int(STR) from public into public static
so now elements from the form itself still have access (i am surprised) to Str2Int()
and from the static Class I Can Access it too....
and its all thanks tp making it into static too ,
am i missing somthing else is there "hidden" drawback when changing Str2Int() from public into public static ?
The point of static code is that belongs to itself, rather than any other object. For this to be true, when you set something as static, everything that depends on it must also be static!
This is what your error message is trying to tell you. You are declaring something as static, but in the computation of that static, you are using something that is not static. Str2Int is not tagged as static, so that is an immediate problem, and it's possible that LoadedRef is also not static. I am half-sure you actually meant to use LoadedRefrnce there, in which case you're fine, but since you spelled nothing correctly I can't be sure!
Check this page for an explanation of the static keyword, also please make more of an effort to read up on C# coding conventions - this makes it much easier for people to read your code when you ask for help like this!
Expanding upon the edits above:
The 'drawback' to making code static is that it pretty much instantly makes everything it is a part of untestable. The idea behind unit testing is to have all of your code broken out into totally replaceable parts, so they can be tested separately and moved out separately (if need be). By making a bunch of code static, you are essentially welding it to any other code it might be a part of. In your own example, by making Str2Int() public static, everything that uses Str2Int() is now untestable!
Static code is, generally speaking, a vice that you should attempt to avoid as much as possible. There are places where you can't, and if you are just starting to learn really the biggest focus is just getting something working. But be ready to look back on this code and go cold at how you could've ever written something so bad in a few years, when you are more experienced and confident in your skills.
add Form object to static class, like this :
public static class MyLoadedBtmpToolBox
{
public static Form MainForm {get;set;}
public static int testStr2Int = MainForm.Str2Int("100");
}
and from the Form :
public partial class MyForm1 : Form
{
private override OnLoad(..){
base.OnLoad(...);
MyLoadedBtmpToolBox.MainForm =this;
}
}
This design is fragile by itself, as you has to gurantee that MyForm property is intialized before it's used to call ..testStr2Int = MainForm.Str2Int("100")...
So, considering that testStr2Int is public, may be intialization of it you can do in Form too and not in static class.

How to get my .net dll to be referenced in vba/com?

i have a .net dll which is written in c sharp, which uses linq to read data and return it to another calling vba app. i didn't plan for this so the initial project was written for it to be accessible by another .net app. so now i just found out that there's a lot of stuff about .net com interoperability and what not.
so i've learned that i need to user interface to make it work, and i need to regasm the dll to create a type library file which i can reference directly from the vba/vb6 app.
as of now i'm getting the problem of when i do this Dim obj As DtasApiTool.Program, it's fine but on the next line set obj = new DtasApiTool.Program will cause an error about New operator not being used properly. when i tested another .net dll from codeproject it works fine.
so my question is, what am i doing wrong here?
am i using too many references, as in
the using system.xxx?
or is it due
to some files that i have in the
projects, i.e. app.config
file, etc.
and how do i get the guid?
as i have very limited knowledge or experience in all of this ,i'm basing what is right or wrong from the example code in code project :( so feel free to comment on anything.
this is the code that i'm using:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.OleDb;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.IO;
//using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
//using System.Windows.Forms;
namespace DtasApiTool
{
[Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7059")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _Program
{
[DispId(1)]
string Get_All_Locales();
[DispId(2)]
string Get_All_Levels(string locale);
[DispId(3)]
string Get_Subjects_ByLocaleLevelId(string locale, int levelId);
[DispId(4)]
string Get_Topic_ByLevelIdLocaleSubjectId(int levelId, string locale, int subjectId);
[DispId(5)]
string Get_Subtopic_ByLevelIdLocaleSubjectIdTopicId(int levelId, string locale, int subjectId, int topicId);
[DispId(6)]
string Get_Skill_ByLevelIdLocaleSubjectIdTopicIdSubtopicId(int levelId, string locale, int subjectId, int topicId, int subtopicId);
[DispId(7)]
string Get_All_Subjects(string locale);
}
[Guid("09FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("DtasApiTool.Program")]
public class Program : _Program
{
...}
}
Hm - I'm using C# DLLs all the time with COM and never had problems. I'm not even using the interface-approach you have there. This is, for example, an anonymized part of a DLL I'm using in Microsoft Dynamics NAV via COM:
using ...;
namespace SomeCOMTool
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MyCOMTool")]
[ComVisible(true)]
[Guid("your-guid-here without curly brackets!")]
public class MyCOMTool
{
/// <summary>
/// Empty constructor used by Navision to create a new instance of the control.
/// </summary>
public MyCOMTool()
{
}
[DispId(101)]
public bool DoSomething(string input, ref string output)
{
}
}
}
Of course "COM visible" is set in the assembly options and there's also a GUID in the respective field.

Categories