0

Premise: This is for learning purpose.

I'm trying to adapt my Console Application code to be served through a WPF Application GUI that I would like to create.

One problem is struggling me.

Actually I'm using something like a procedural approach, even if it's async in some path, how I could decouple my code to be the server for a WPF application View?

Actually I have models representing the managers, some helpers with function to edit queries that I got from controller, and DB Entities, scaffold-ed from an existing DB.

Example:

        static async Task Main(string[] args)
            {
                //IConcessionario sisal = new Sisal();
                IManager pManager = new PrimaryManager(new HttpClient());

                UserController controller = new UserController(new DBContext());

                List<UserQuery> userQueries;

                Console.WriteLine("Starting");

                userQueries = await pManager.GetAllUsersQueriesAsync(users);

                Console.WriteLine("InsertInDb");

                /* code to insert data in db */

            }

        public class UserController {
            private DBContext context;

            public UserController(DBContext context)
            {
                this.context = context;
            }

            public function List<User> GetAll(){
                await using (var ctx = new DBContext())
                {
                    return context.Users
                                .Where(s => s.Active == true)
                                .Select(s => new User() { /** code to populate **/ }));
                }
            }
        }

        public class PrimaryManager : IManager {
            private readonly HttpClient client;

            public PrimaryManager(HttpClient client)
            {
                this.client = client;
            }

            public function List<UserQueries> GetAllUsersQueriesAsync() 
            {
                var queries = new List<UserQuery> queries;

                foreach(var user in users)
                {
                    var query = new UserQuery(){ /* code to populate */ };
                    queries.Add(query);
                    Console.WriteLine($"Added {user.Name} query {query.id}");
                }
            }
        }
  1. Look at Console.WriteLine I put everywhere, how I could move it away from code and modify it to be catched at the same way from the console app and the WPF view?

  2. I'm writing here because I miss the fundamental like: Should my WPF application be aware of the other solution? Should I reference it?

1
  • I took the freedom to change the title so it fits better to the main question. Please double check if I got your intentions right.
    – Doc Brown
    Feb 19 '20 at 6:54
2

The standard approach to decouple a class like PrimaryManager from console output is to use dependency injection. Simply inject the output function either at the call to GetAllUsersQueriesAsync, or (probably better) inject it through the constructor:

    public class PrimaryManager : IManager {
        private readonly HttpClient client;
        private Action<string> outputFunc;

        public PrimaryManager(HttpClient client, Action<string> outputFunc)
        {
            this.client = client;
            this.outputFunc = outputFunc;
        }

        public List<UserQueries> GetAllUsersQueriesAsync() 
        {
            var queries = new List<UserQuery> queries;

            foreach(var user in users)
            {
                var query = new UserQuery(){ /* code to populate */ };
                queries.Add(query);
                outputFunc($"Added {user.Name} query {query.id}");
            }
        }
    }

In the Main function of your console application one can use this class now like this:

  IManager pManager = new PrimaryManager(new HttpClient(), s => Console.Writeline(s));

In a WPF application, you can provide a completely different output function: for example, a function which collects these outputs in a text box in a thread safe manner.

To your second question: technically, with .NET, you could make your WPF application reference your console application directly like a DLL, even if it is compiled to an EXE, but I would recommend against it. The layering of your application will become more apparent when you split this up into 3 assemblies:

  • one EXE for the console application

  • one EXE for the WPF application

  • one DLL which holds the common code and which is independent from console output or any WPF code (this one should be completely unaware of WPF specific assemblies like System.Xaml, for example). It contains classes like your ´PrimaryManager` and must be referenced from the two former assemblies.

3
  • Hi doc, thanks for the answer and for correction you've made in my question. With Dll you mean a Class Library Project? What if would like to create a .NET Core app instead of Net Framework? Is still viable this approach?
    – exSnake
    Feb 19 '20 at 18:13
  • Another question. when creating a DLL how i can refers to dll functions, from wpf or console app?
    – exSnake
    Feb 19 '20 at 18:38
  • 1
    @exSnake: 1.) yes, in Visual Studio you pick "Class Library Project" to create a .NET DLL. 2) Sure, what I wrote has nothing to do with .Net Core vs. .Net Standard (and if you had just tried it out, I am sure you could answer this by yourself in a few minutes). 3) This is basic programming stuff, google for "C# create class library project" and you will find plenty of tutorials, like this one
    – Doc Brown
    Feb 20 '20 at 5:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.