I found this code sample on MSDN website. My question is regarding the last line where they instantiate the class in the main method. But is that necessary? According to the documentation on Installutil:
Installutil.exe uses reflection to inspect the specified assemblies
and to find all Installer types that have the
System.ComponentModel.RunInstallerAttribute attribute set to true. The
tool then executes either the Installer.Install or the
Installer.Uninstall method on each instance of the Installer type.
So does it mean that the main method and the instantiation of the MyEventLogInstaller-class is not necessarty?
using System;
using System.Configuration.Install;
using System.Diagnostics;
using System.ComponentModel;
[RunInstaller(true)]
public class MyEventLogInstaller: Installer
{
private EventLogInstaller myEventLogInstaller;
public MyEventLogInstaller()
{
// Create an instance of an EventLogInstaller.
myEventLogInstaller = new EventLogInstaller();
// Set the source name of the event log.
myEventLogInstaller.Source = "NewLogSource";
// Set the event log that the source writes entries to.
myEventLogInstaller.Log = "MyNewLog";
// Add myEventLogInstaller to the Installer collection.
Installers.Add(myEventLogInstaller);
}
public static void Main()
{
MyEventLogInstaller myInstaller = new MyEventLogInstaller();
}
}
Related
Newby c#/asp.net question here. I am creating a website with .aspx pages.
Within a method I have created a list and added items to it as shown below:
var footballTeams = new List<string>();
footballTeams.Add("Arsenal");
footballTeams.Add("Aston Villa");
footballTeams.Add("Bournemouth");
footballTeams.Add("Brentford");
footballTeams.Add("Brighton & Hove Albion");
footballTeams.Add("Chelsea");
However, I want to move this code into its own separate class - so it is easier to update the teams rather than have to go deep into code.
How would I code this in a class and then be able to call and use the list from another class.
I have tried creating a new folder called App_Code. And then putting a dummy method in it as shown below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace FootballResultPredictor.App_Code
{
public class Class1
{
public static String MyMethod()
{
string myString = "test";
return myString;
}
}
}
However when I try to call the method from the other class, it just can't seem to find it at all as shown here:
Below is the file structure:
I am trying to call a method in Class1.cs from StartNewSeason.aspx
Looking quickly at your code, I have some comments.
-Don't put your new class in a separate folder.
-This code is wrong: string a=myMethod();
because you can't call a method before you have an instance (new...) of a class unless the class is a static class, which is not the case here.
-Coding string b=Class1.MyMethod(), is better, but still wrong, since Class1 is the name of the class not the name of the object.
At this point, I guess the concept of the class and the class object are somewhat not very clear to you.
I suggest that you review this fundamental concept as it is the core of Object Oriented Programming. Also using ASP.NET at this point of your learning path is highly not advisable, I highly recommend that you get to learn OO fundamentals through C# console applications or Windows Forms. These two frameworks, are much simpler to deal with.
When you create a class (of .cs type) file under the same solution in VS it would have a namespace and a class definition. If the class is not static, you refer to it as (other ways can be used as well):
myClassName ObjectName = new myClassName();
The namespace can be specified if the class is in a different project, like new NameSpace2.myClassName, but this is not the case here.
Only after you create an instance (an object) of the non-static class, you can use the object and its method using the ObjectName (not the myClassName). For exmaple:
ObjectName.MethodName();
Back to the program at hand, here is one way to have a separate class handle the list. There are many ways to do this, this way provides validation and allows you to iterate over the list items. Let me know if this is not clear.
The new class is here:
//using System;
//using System.Collections.Generic;
//using System.Data;
public class FootballTeams
{
public List<string> footballTeams = new List<string>();
public FootballTeams()
{
//initialize the list
this.AddFootballTeam("Arsenal");
this.AddFootballTeam("Aston Villa");
this.AddFootballTeam("Bournemouth");
this.AddFootballTeam("Brentford");
this.AddFootballTeam("Brighton & Hove Albion");
this.AddFootballTeam("Chelsea");
}
//Method to add a new team
public void AddFootballTeam(string parmTeam)
{
//validate input
if (string.IsNullOrWhiteSpace(parmTeam))
{ throw new NoNullAllowedException("Error:Team name is empty"); }
if (footballTeams.Contains(parmTeam))
{ throw new DuplicateNameException(); }
//if valid add the name to the list
footballTeams.Add(parmTeam);
}
}
A sample usage of the above class is:
var _t = new FootballTeams();
try
{
_t.AddFootballTeam("Ringers");
}
catch (Exception _ex)
{
Console.WriteLine(_ex.Message);
return;
}
foreach (var _team in _t.footballTeams)
{
Console.WriteLine(_team);
}
I have created a unit test for a method in a class called game.cs. For some reason, when I reference the class, I am unable to create a new instance. How do I make this class accessible so I can test my code?
File Hierarchy and solution:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BowlingKataTDD;
namespace BowlingKataTDDTest
{
[TestClass]
public class BowlingKataTDDUnitTests
{
[TestMethod]
public void DoesGameExist()
{
//arrange
BowlingKataTDD.
}
}
}
BowlingKataTDD Project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BowlingKataTDD
{
class Game
{
static void Main(string[] args)
{
}
}
}
The reason you do not see the classes is that they are non-public (internal by default).
There are two solutions to this:
If you would like to make your classes visible to outside users, make them public
If you would rather not publish your classes, use InternalsVisibleTo attribute.
To use the second solution, open AssemblyInfo.cs and add the following line:
[assembly: InternalsVisibleTo("BowlingKataTDDTest")]
BowlingKataTDDTest is the name of your assembly, as defined in the project file.
Make the class public, as well as any members of that class which need to be invoked externally (such as by a unit test):
public class Game
{
public static void Main(string[] args)
{
}
}
This is a common mistake with calling libraries with new projects, and I was able to resolve it. Often easy to forget to change the modifier to public from the project in Visual Studio, because by default a new project template creates the class though without it being set to public. When changing the Game class to public, am able to instantiate the Game object.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BowlingKataTDD;
namespace BowlingKataTDDTest
{
[TestClass]
public class BowlingKataTDDUnitTests
{
[TestMethod]
public void DoesGameExist()
{
//arrange
BowlingKataTDD.Game game = new BowlingKataTDD.Game();
}
}
}
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
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.
I have a system that reads through a folder and saves the paths to an array list. this folder contains a bunch of class files ".cs" all of these classes implement an interface called BaseScript.
I am attempting to find the class name so that I can call class methods but you are supposed to be able to add class files to this folder on a regular basis, so I cannot hardcode the objects to be created.
e.g. I have a file called "Manufacturing.cs":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LLS
{
class Manufacturing : BaseScript
{
public void init()
{
Console.WriteLine("Manufacturing...");
}
public void uninit() { }
public void recomp() { }
}
}
It implements "BaseScript":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LLS
{
public interface BaseScript
{
void init();
void uninit();
void recomp();
}
}
I need to be able to use the path: "\Scripts\Manufacturing.cs" to call something like
BaseScript[] s = {new "Manufacturing class name"}
I know there must be some roundabout way of doing this.
how can I find the class name and then create an instance from that class?
If your class is in the same assembly then you can create an instance of the object by using Activator.CreateInstance. I didn't try your code on my side. So casting might not work. Double check this code:
BaseScript s = (BaseScipt)Activator.CreateInstance(null, "Namespace.TestClass");
Edit-I mistakenly though you had dlls and not cs files for some reason.
As others say you are not properly explaining the scenario. But from what I understand you are probably implementing a plugin type of pattern here.
In order to call methods on C# classes you may add later on, you need to iterate through the folder, get the *.cs files, compile them and then using reflection, load the assembly and create an instance of a class you know exists(you should know the fully qualified name of the class beforehand). Finally, you should find the method you want to call and then call it using reflection. Here is some code to get you started:
Microsoft.CSharp.CSharpCodeProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new System.CodeDom.Compiler.CompilerParameters();
parameters.GenerateInMemory = true;
//You should add all referenced assembiles needed for the cs file here
//parameters.ReferencedAssemblies.Add();
var files = new System.IO.DirectoryInfo("Scripts").GetFiles("*.cs");
foreach (System.IO.FileInfo file in files)
{
System.CodeDom.Compiler.CompilerResults result =
provider.CompileAssemblyFromSource(parameters, new[] { System.IO.File.ReadAllText(file.FullName) });
object instance = result.CompiledAssembly.CreateInstance(file.Name);
if (instance is BaseScript)
{
//Do processing on (BaseScript)instance
}
}