writing dll , c# (concept) - c#

I have a basic question.
1-
I want to use Science.dll provided at
http://www.sciencecode.com/
I want to add some new functions in some XXX.cs files and also some new YYY.cs files. Then I want to make dll of them again (Science.dll with changes) and use it. How it can be done.
Should I make a new project and add all more than 100 files (already given on website) in that project and some my new YYY.cs files and then what should be next step???
2-
I wanna ask about best way to put many different functions in one 'utilities.cs' file. Say I have different static functions *printmatrix, read_text_file,* etc. What should I do, so that I directly use them in main program. What should be the way in c#.In c++ I wrote header file and cpp file named utilities and then I used these functions.
Any good idea.

You cannot modify an existing assembly unless you have the source code of it. What you could do is create a new class library project in Visual Studio, add Science.dll as a reference and then add your own functions which could use functions in the referenced assembly. When you compile your project it will produce another assembly.

First you make a new project taht has reference on the science.dll.in Visual studio
You can inheritance its class and add yours functionality.
You can use partial class that has the same name as in the science.dll. and add your functionality
eg:
science.dll
public class Calc
{
public Int32 Add(Int32 a, Int32 b){..implementation...}
}
yourproject.dll
public partial class Calc
{
public Int32 Minus(Int32 a, Int32 b) {..implementation..}
}
You can use extension method with your functionality. This is depend on your implementation.
For detail implementation you can see on MSDN : http://msdn.microsoft.com/library for both C# and VB.NET on both syntak
In the caller project, make sure add reference both science.dll and yourproject.dll.

Related

Different DLL versions, one codebase

In my projects I have to interact with an ERP system that exposes about 30 different API DLLs.
The ERP company systematically creates new versions of their system and I'm forced to change the DLLs to the new versions. However, not all of my clients update the ERP, so I'm also forced to maintain old references. My current solution to this problem is:
1) For every ERP version I create an 'ApiWrapper' project, referencing the DLLs for this ERP version.
2) In my main project I reference those 'ApiWrappers' and use a selected one of those.
An example function inside of the 'ApiWrapper' looks like this:
public void AddContractorAttribute(Ustawienia settings, string attributeCode, string attributeValue, int contractorId)
{
CreateNewSession();
CDNHeal.Kontrahenci AllContractors = (CDNHeal.Kontrahenci)session.CreateObject("CDN.Kontrahenci", null);
CDNHeal.IKontrahent SelectedContractor = (CDNHeal.IKontrahent)AllContractors[$"Knt_KntId = {contractorId}"];
CDNBase.ICollection AllAttributes = (CDNBase.ICollection)(session.CreateObject("CDN.DefAtrybuty", null));
CDNTwrb1.IDefAtrybut SelectedAttribute = (CDNTwrb1.IDefAtrybut)AllAttributes[$"dea_Kod = '{attributeCode}'"];
CDNTwrb1.IKntAtrybut NewAttributeValue = (CDNTwrb1.IKntAtrybut)SelectedContractor.Atrybuty.AddNew(null);
NewAttributeValue.DefAtrybut = (CDNTwrb1.DefAtrybut)SelectedAttribute;
NewAttributeValue.Wartosc = attributeValue;
session.Save();
}
Now, the problem I have is: if I want to add or change a function in the ApiWrapper, I have to do it in every single one of those. They don't differ code-wise, they only reference a different set of DLLs. Is there a way to solve this issue through class inheritance or otherwise?
You can design a class that will be implemented with the builder pattern or factory method (use some creational pattern, please read about these patterns it will help you reduce your codebase). The approach is to design one generic class which will be used everywhere. So, you can modify it easily. You need to figure out how to distinguish your dlls. Dll's References could be distinguished in two ways:
by the full name of the assembly (usually it includes the version
of assembly).
or you can load all dlls into memory and
reflectively read dll's version.
After distinguishing versions you can easily put all dlls together and ship it.
So, basically you should design a generic builder, which will take a version number as a parameter and return a well-prepared bench of dlls.
Hope it helps.

C# code expansion/injection in compile time

I'm looking for a way to expand/inject code at compile time,
something like templates/macros/snippets...
Let's say I wrote this code in a lot of places in my application:
[JsonObject("MyProperty")]
private string MyPropertyJson { get; set; }
public object MyProperty { get; set; }
The MyPropertyJson property is used for EF mapping purposes only so I save the value is a JSON string in DB but for class users, they only know about MyProperty property.
What I want to do is, at compile time, MyPropertyJson to be expanded to this:
private string MyPropertyJson
{
get
{
return JsonConvert.SerializeObject(MyProperty);
}
set
{
MyProperty = JsonConvert.DeserializeObject(value);
}
}
I want this to be done in the output binaries only without affecting the source code.
I know about Unity, PostSharp, Aspect-Injector, etc.. but they don't achieve what I want because by using them, I have to use some reflection to find & manipulate MyProperty but I want to expand it exactly like it's been written in the same class with access to all class internals.
It's exactly like code snippets but to be expanded during compilation phase.
A solution that doesn't cost anything extra and is supported within Visual Studio is T4 aka Text Templates. However, it does require you install the VS SDK (eg, 2015) and Modeling SDK (eg, 2015) of the version of VS that you use.
For my base class libraries, I end up dedicating an assembly for utils to use in the T4 code I write in production code. I use it in places like rolling out read/writes for primitives in IO code (eg, .TT and .CS). Although you don't have to do this if you don't need much/complex compile time code gen.
I was able to achieve my requirement by writing a BeforeBuild msbuild target to call an external console app which I've developed to:
Copy source files that will be rewritten to a temp folder
Rewrite the source code in the temp files
Added conditional Compile tag to the .csproj file to include manipulated source files instead of the original ones
It works like a charm :)
I'm working on a generic engine for this task and will commit it to github once finished.
The is a way to kind of get what you want.
Using implicit operators
That would need to create your own json object class for example, then add these:
class JsonObject {
public object obj;
public static implicit operator string(JsonObject target) {
return Json.SerializeObject(target.obj);
}
}
But that won't really do what you really wanted. Almost the same as creating a new class and add functions.

A better alias list?

We have a system that manages generic physical resources. There are over 500 individual resources. The system is used for many different things and to make the software easier to write we use aliases.
For example, a physical resource TG67I9 is given an alias of "RightDoor". When code is written RightDoor is used instead of TG67I9 making the code more readable. This alias list is loaded as a text file with references to resources and their aliases. This system uses literally hundreds of different alias lists to reference the same physical resources.
This type of setup has two major shortcomings. First, when resources are called using their aliases, they are passed in as strings. Door.Open("RightDoor") for example. This does not give any tooltips or smart anything making the code more difficult to write. It basically requires constantly referencing the alias list. Is it RightDoor or Right_Door or right-door or... you get the idea. The second is that there is no validation of parameters until execution. All the compiler knows is that a string is passed in and then it's happy. Only when the code is run, the function tries to access the resource through its alias and fails because it can't find right-door because it's supposed to be RightDoor. An error is displayed. This requires tedious debugging and running the code over and over to weed out any bad aliases.
Is there a better way to do this? Such that an alias list can be made with a cross-reference of physical resources to their alias names and after the list is made that tooltips could appear suggesting resources. (Assume that a new system could be written from scratch)
I'm using the latest .NET with VisualStudio 2017 and C# to write the code.
The simplest approach is most likely a "string enum":
public class Resources {
public const string
LeftDoor = "TG67I8",
RightDoor = "TG67I9";
}
Sample use:
Door.Open(Resources.RightDoor);
Hovering over .RightDoor in VS shows a tooltip (constant) string Resources.RightDoor = "TG67I9"
Right-clicking .RightDoor and selecting Find All References will show where the variable is used.
Another option can be adding the strings in the Resources section of the Project Properties, and then:
using YourProjectNameSpace.Properties;
...
Door.Open(Resources.RightDoor);
That is a bit slower, because the resource(s) are retrieved at run-time, but allows to load the resources from a custom external file separate from the executable.
Use a static class with constants. I have done the same many times and still do. Plus .NET does this as well.
public static class PhysicalResources
{
public const string One = "Uno";
public const string Two = "Deux";
// ...
}

How to use same method name in different dlls in C#? [duplicate]

I have two DLL files that have the same namespace but they have different methods and types.
How can I reference both DLLs in my project and use their methods and types?
By the way, these two DLLs have some methods and types with the same name but different implementation and some unique methods and types.
There's nothing special you need to do - just reference them and use the types. Namespaces can span accross several assemblies without problems, because they're not really opaque types. A namespace is just a way of adding a common prefix to all the types it contains, allowing you to have multiple types of the same name under different namespaces. (The framework doesn't see them as having the same names, because it sees the "fully qualified" name of everything - which has an alias and a namespace attached to the front of it.)
In the rare event that you reference 2 assemblies which have the same type names and the same namespaces (such as 2 different versions of the same dll) - you can distinguish which assembly to use for a given type using an alias. The default alias for all references is global, but you can specify your own alias for any assembly when you reference it (using a compiler switch - or just use the properties box in Visual Studio) - and have an extern alias <name> clause at the top of your code file where you use it - you would access the types from different assemblies with <name>::MyNamespace.Type
If you have 2 types with the exact same name (note that the name includes the namespace) but in different DLLs and you are interested in using both of them, then you can do this.
Short Answer
You have type Acme.Foo in 2 different DLLs and you want to use them. Give the reference an alias in the reference properties window (View | Properties Window) then use it like this:
extern alias TheAliasYouGaveTheReference
TheAliasYouGaveTheReference::Acme.Foo f = new
TheAliasYouGaveTheReference::Acme.Foo();
The default namespace is global for any C# program but note above we are using the alias we created instead of global.
The best approach is to NOT get into a situation like this in the first place, if both assemblies are your own, then do not create 2 types with the exact same name in the exact same namespace. But sometimes we do not control the source code so for those times, the above solution can be used.
Long Answer
I am copying most of the article from here so it is recorded here in case the article is no longer available.
How do you get into a situation like this?
Firstly, here is how you can replicate the scenario so it is really clear what we are talking about:
Create a C# Class Library called FooVersion1
Replace the template code in Class1.cs with the following:
using System;
namespace Acme
{
public class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
Right-click on the solution in solution explorer and select Add | New Project
Save the current project (only applicable in express)
Select a Class Library in the new project dialog and change the project name to FooVersion2 and press OK
Replace the code in Class1.cs with the following:
using System;
namespace Acme
{
public class Foo
{
public void Bar()
{
Console.WriteLine("Bar");
}
public void Goo()
{
Console.WriteLine("Goo");
}
}
}
Usage of the type in Application
Ok so now we have 2 different assemblies containing Acme.Foo. Let's now create a console application and try to use each one.
Right-click on the solution in solution explorer and select Add | New Project
Select a Console Application and call it Consumer
Right-click on Consumer and select ‘Set as startup project’
Right-click on the references node in the Consumer project and select ‘Add Reference’
Click on the projects tab, and multi-select FooVersion1 and FooVersion2
Click OK
Add the following line to Main in the Program type of the Consumer project:
Acme.Foo f = new Acme.Foo();
Build the solution via Ctrl+Shift+B (or F6)
Notice that you get two build errors [as shown below]:
The Fix
Here is how we can fix it:
Open solution explorer and select FooVersion1 in the References folder of the Consumer project
Hit F4 (or select View | Properties Window)
Change the Aliases property to FooVersion1
Build the solution
Now everything will build correctly, because Acme.Foo unambiguously refers to FooVersion2
Add the following directive to the top of Program.cs in the Consumer project:
extern alias FooVersion1;
Change the usage of Acme.Foo to:
FooVersion1::Acme.Foo f = new FooVersion1::Acme.Foo();
f.Bar();
Notice that when you type ‘f.’ the completion list contains only those methods in FooVersion1 of Acme.Foo (notably it does not include Goo)
Build the solution and everything will build correctly
Finally add the following code under f.Bar() in Program.cs of the Consumer project:
Acme.Foo f2 = new Acme.Foo();
f2.Goo();
Notice that f2’s completion list contains Goo.
Build again using Ctrl+Shift+B and notice that there are still no build errors
you can use the alias feature of the /reference (Import Metadata) (C# Compiler Options) compiler option to solve your problems, read from here for more details

How to use more than one RESX file

I am working on porting an iOS App to WP8. The iOS app is localized to 5 different languages. The localized strings are stored in different files. For example "app.strings" hold all strings unique for the app and "common.strings" hold strings that are used in other apps as well. Of course there are 5 versions of each .strings file (app.de.strings, app.en.strings, ....).
In the iOS code I can simple refere to "String_ID_123" and the system will automatically search for that string in all .strings files and display the correct value, no matter if this string can be found in app.strings, common.strings or elsewhere. Is this possible on WP8 as well?
VS automatically created two files to support localization:
AppResources.resx which holds the actual strings (with AppRessources.Designer.cs as code behind)
LocalizedStrings.cs which is a helper class to support binding
Of course I could add additional .resx files to the project and use them create the same structure as in the iOS project. But then I would have to add additional versions of LocalizedStrings.cs (e.g. LocalizedStrings_Common.cs) which refere to the correct .resx as well. Then I would have to explicitly use the correct Souce in XAML.
I would have to know where String_ID_123 is defines. Is there any way to let XAML/C# do that automatically?
I'm afraid VS isn't gonna help you with this. First, you cannot address String_ID_123 without specifying the resource file it resides in. Second, when you add additional resource files (e.g. CommonResources.resx) VS will not modify LocalizedStrings for you. You will have to do that yourself.
public class LocalizedStrings
{
private static AppResources _localizedResources = new AppResources();
private static CommonResources _locallizedCommonResources = new CommonResources();
public AppResources LocalizedResources { get { return _localizedResources; } }
public CommonResources LocalizedCommonResources { get { return _locallizedCommonResources; } }
And third, when you add new languages to your project, VS will generate AppResources.fr.resx for you but will not generate CommonResources.fr.resx. You'll have to add a copy your self.

Categories

Resources