3

I am creating a project in Visual Studio 2010 using C#.

I have my main (program.cs) and several different classes in different file (class1.cs class2.cs class3.cs), and each class has its own function.

I was wondering if there is a way to set a variable (say in program.cs) that's accessible from each different class files?

To reduce confusion, I'll explain in example.

The program.cs is to create files. Each class is to create different type of files (txt, xml, xls, etc). I want to specify the path to save the file in program.cs, so if I want to change the path, I only have to change it in one place.

I want to set up a variable that's accessible from each class file, instead of passing the 'path' variable into the functions.

Is there a way to do so?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
sora0419
  • 2,308
  • 9
  • 39
  • 58

8 Answers8

5

This kind of problem (a readonly value needed during execution of your app) could be solved adding a new settings through the setting property editor of your main project.

  • Right click on your project
  • Select properties
  • Select the Settings tab (create the file if needed)
  • Type the name for your setting (I.E. PathToExport)
  • Select Type String, Scope Application and type your initial configuration path

Now you can access this value from everywhere in your classes using

string path = Properties.Settings.Default.PathToExport;

Of course it is always possible to define, inside a class a static property and read this value, but writing a fixed path in the executable of a program is a very bad idea. If you want to change it you need to recompile and redistribute the application. Using the exe.config file you have a cleaner separation of code from configuration. (And changing the path to a shiny new server location requires to modify just the exe.config file)

Steve
  • 213,761
  • 22
  • 232
  • 286
  • +1 to your answer because it is indeed better than using constants, I'm just used to working with _un_ distributed apps. Still, "you'd be fired at my place" is not an argument. – user247702 Jun 18 '13 at 15:57
  • @Stijn don't take it personally. It is a set of rules that you learn the first day you start to work in some places and then they become a second skin. Sometimes they are universally correct sometimes they are right for the shop, sometime they are just crap. See you again on SO :-) – Steve Jun 18 '13 at 16:03
  • @Stijn just noticed that you have deleted your answer. Why? It is formally correct. Just add some warnings about the use of constants and it is still a good answer – Steve Jun 18 '13 at 16:05
  • @Steve Thanks for your ans. I'm a bit lost after the select properties step. Which tab do you go to to type in settings? – sora0419 Jun 18 '13 at 16:08
  • Sorry, it is the Settings tab. If you don't have a settings file it will be created for you. After inserting the new setting you could change the value using this editor or manually in app.config. However I recommend, during development, to change the value using the VS Settings editor – Steve Jun 18 '13 at 17:01
  • 1
    @Steve don't worry, I'm not taking it personally :) Removed my answer because I don't think it's useful to keep a subpar answer around, and yours includes the warning about using consts. – user247702 Jun 18 '13 at 23:08
1

You can do this using a public static property.

static class Program
{
     public static string Path
        {
            get { return path; }
            set { path = value; }
        }
     static string path = string.Empty;
}

So you can access the Path with Program.Path

1

You're looking for a static property or field:

public class Program
{
    public static string TargetDirectory = @"C:\MyDirectory";
}

public class SomeOtherClass
{
    public void SomeMethod()
    {
        var directory = Program.TargetDirectory;
    }
}
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
0

Make a class e.g. MainClass, and derive your all three classes from that class.

class1.cs : MainClass

class1.cs : MainClass

class1.cs : MainClass

Now create a variable in your MainClass with access type protected like:

protected string path = "what ever you path";

For your case, it would be better to make it static as well:

protected static string path = "what ever you path";
Shaharyar
  • 12,254
  • 4
  • 46
  • 66
  • @LionelD What makes you think so? It is entirely up to the designer of the class hierarchy to decide what's a good choice in his case; he did not tell us enough to make an informed decision. – Sergey Kalinichenko Jun 18 '13 at 15:47
  • 1
    Why -1??? He asked for a way to solve the problem. It is not the best, but still the correct answer for the question. – Shaharyar Jun 18 '13 at 15:51
0

You can do so.
The program.cs is static and you can access it from all your classes in the same project.
You can declare a static readonly property in the program.cs and all your classes can call the property as program.[yourproperty].

Venugopal M
  • 2,280
  • 1
  • 20
  • 30
0

you can either create a constante variable in your program.cs file or another one or you can create a static field or a static property that returns your string.

Hope this helps.

Lionel D
  • 317
  • 1
  • 10
0

You can create a static variable, as those are accessible from anywhere in your code. Most likely you will want to wrap this in a Static service class, such as below...

public static class AppSettings
{
  public static string GlobalFilePath {get; set;}
}

then in your code you can say AppSettings.GlobalFilePath = @"C:\Wherever"

David C
  • 3,610
  • 3
  • 21
  • 23
0

Your classes should be related somehow:

class Program
{
    public string PathForSavingFiles { get; set; }
}

abstract class FileBase
{
    private readonly Program program;

    protected FileBase(Program program)
    {
        this.program = program;   
    }

    public void Save()
    {
        Save(program.PathForSavingFiles);
    }

    protected abstract void Save(string path);
}

class TxtFile : FileBase { ... }
class XlsxFile : FileBase { ... }
// etc

As an option, you could use dependency injection (MEF sample):

interface IInfrastructureProvider
{
    string PathForSavingFiles { get; }
}

class Program : IInfrastructureProvider
{
    public string PathForSavingFiles { get; set; }
}

abstract class FileBase
{
    private readonly IInfrastructureProvider provider;

    [ImportingConstructor]
    protected FileBase(IInfrastructureProvider provider)
    {
        this.provider = provider;   
    }

    public void Save()
    {
        Save(provider.PathForSavingFiles);
    }

    protected abstract void Save(string path);
}

This allows you to mock IInfrastructureProvider for testing purposes and keeps your components loosely coupled.

Avoid static fields, properties or another variants of global state (e.g. settings), if it is possible. The more global state you have now, the more headache you'll have later.

Dennis
  • 37,026
  • 10
  • 82
  • 150