|
Simple enough:
private void M2_SaidaEfetiva_Click(object sender, EventArgs e)
{
var theForm = Application.OpenForms.OfType<Frm_Saida>().FirstOrDefault();
if (theForm is null)
{
theForm = new Frm_Saida();
theForm.MdiParent = this;
theForm.Text = "Saídas Efetivas";
theForm.Tag = "1";
theForm.Show();
}
theForm.Activate();
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi all,
I would appreciate a hand in designing my code.
I have a number of classes for different entities (currently 7 but there can be more in the future). I need a method in each of these classes that authorizes user's access to a file resource. Implementation varies but an exception must be thrown if user does not have access to the file in question.
Problem is, when the file is being accessed, I need to call the authorization method of the correct class based on the data on the file. Files are stored in a db table and one of the fields in that table determines which entity the file is related to and how to find which user has access to the file.
So I must read the file data from db, then see which entity it's related to and then call the authorization method of the correct class.
Is there a way in C# to accomplish this without having to make a switch case structure on the file field value and initialize a class and call a method?
Example of the classes used:
public class FileAttachment
{
protected void AuthorizeFileAccess(FileAttachmentData file)
{
}
}
public class ChatMessage
{
public int SenderUserId;
public int RecipientUserId;
}
|
|
|
|
|
Your words: "read the file data from the db"; i.e. no switch. The "file data" would identify the "class type" to be instantiated for your "method call".
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it.
― Confucian Analects: Rules of Confucius about his food
|
|
|
|
|
I am baffled by how the code in the 'Human and 'Cat classes can successfully call a generic static method (SetCache<T>(T value) ) without supplying the usual <Type> adornment.
Here's a sample usage of the code:
BeingCache cache = BeingCache.CacheInstance;
Human ahuman = new Human("joe", "male");
Cat acat = new Cat("Meow", true);
IBeing b1 = cache[1];
IBeing<Cat> b2 = (IBeing<Cat>) b1;
Cat cat = b2.IBInstance;
bool st0 = b2 is Cat;
bool st1 = b2 is Being<Cat>;
bool st2 = b2 is IBeing<Cat>;
Cat hepcat = BeingCache.GetBeing<Cat>(cache[1]);
IBeing<Cat> b3 = (IBeing<Cat>) cache[1]; The example: note that classes 'Human and 'Cat do not inherit from anything.
using System;
using System.Collections.Generic;
namespace InterfaceInheritance_2020
{
public class Human
{
public Human(string name, string gender)
{
Name = name;
Gender = gender;
BeingCache.SetCache(this);
}
public string Gender{ get;}
public string Name { get; }
}
public class Cat
{
public Cat(string name, bool haswhiskers = true)
{
Name = name;
HasWhiskers = haswhiskers;
BeingCache.SetCache(this);
}
public bool HasWhiskers { get; }
public string Name { get; }
}
public interface IBeing
{
Type BeingType { set; get; }
}
public interface IBeing<T> : IBeing
{
T IBInstance { set; get; }
}
public class Being<T> : IBeing<T>
{
public Being(T content)
{
IBInstance = content;
BeingType = typeof(IBeing<T>);
}
public Type BeingType { get; set; }
public T IBInstance { get; set; }
}
public sealed class BeingCache : List<IBeing>
{
private BeingCache()
{
}
public static BeingCache CacheInstance{ get; } = new BeingCache();
public static void SetCache<T>(T value)
{
CacheInstance.AddBeing(new Being<T>(value), typeof(T));
}
public void AddBeing(IBeing being, Type btype)
{
being.BeingType = btype;
CacheInstance.Add(being);
}
public static T GetBeing<T>(IBeing being)
{
return (T) ((IBeing<T>) being).IBInstance;
}
}
}
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
The type is inferred because you pass in a value of the type in your call
public static void SetCache<T>(T value)
"I didn't mention the bats - he'd see them soon enough" - Hunter S Thompson - RIP
|
|
|
|
|
Hi, Appreciate your response. I am still baffled: when BeingCache.SetCache is called within the two non-generic classes 'Human and 'Cat ... like this:
BeingCache.SetCache(this); // :wtf:
How does the generic static method:
public static void SetCache<T>(T value) ''
not throw a compile time error, or a run-time error ?
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
I had a similar conversation with jsop on here who wrote an excellent article on using reflection in a DAL - he had the method below in one of his classes
public static T ConvertFromDBValue<T>(object obj, T defaultValue)
{
T result = (obj == null || obj == DBNull.Value) ? default(T) : (T)obj;
return result;
}
and he made calls like this
object propvalue;
Type proptype;
propvalue = ConvertFromDBValue(propvalue, proptype.GetDefaultValue());
It just works - however if you change the parameter T defaultValue to a type other than T it won't compile unless you provide the type in <>.
"I didn't mention the bats - he'd see them soon enough" - Hunter S Thompson - RIP
|
|
|
|
|
A revelation to me Being able to do this saves me the trouble of having the non-generic classes inherit from a generic-typed abstract class that calls 'SetCache<whatever>
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
Indeed
"I didn't mention the bats - he'd see them soon enough" - Hunter S Thompson - RIP
|
|
|
|
|
If you call
SetCache(x);
and "x" is type string then it compiles
SetCache<string>(x);
if "x" is an int then it compiles
SetCache<int>(x);
whatever type "x" is it assumes the type between the angled brackets is that type. The only time you absolutely have to supply the type is when the IDE can't work out itself what the type is. For example if you have
T GetCache<T>(string key)
then the IDE can't workout what "T" should be from the params
GetCache("username");
In the above code there is no way to work out what GetCache returns so you have to explicitly say;
GetCache<string>("username");
|
|
|
|
|
Thanks, this is a revelation to me
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
F-ES Sitecore wrote: then the IDE can't workout ... I think you mean the compiler.
|
|
|
|
|
I initially wrote the compiler but I didn't know if it was the compiler or VS, but thinking about it it's obviously the compiler
|
|
|
|
|
|
thanks, Richard, it made my day to discover another thing i should have known
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
Thank you, all, for your illuminating responses ! Any further ideas, comments, critiques, would be very appreciated. If you care to address the more theoretical issue of whether this example embodies a design-pattern, I am all ears. Is the facility to "rehydrate" from instances of objects cast to interfaces to the ab origine strongly typed instance a form of factory pattern, or just a hack to enable collections of mixed types in C#'s strongly typed codeaverse >
a message for: @RichardDeeming @HaroldAptroot @jschell
If you have time to consider what this code does in the light of your comments on my April 24th. post and code example: [^] ... does this example meet my stated goal of:Quote: the goal: use interfaces to enable creating a collection of different types of objects: and, then, at run-time, cast back to the generic type without hard-coding specific types.
a. without using 'dynamic
b. without using reflection
c. without cloning/copying (using something like 'Activator.CreateInstance)
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
I'm not sure. How I interpreted your previous post was that you wanted something like this
IBeing<Cat> b3 = (IBeing<Cat>) cache[1];
Or this
Cat hepcat = BeingCache.GetBeing<Cat>(cache[1]);
Except without mentioning Cat (writing IBeing<Cat> or GetBeing<Cat> or even just Cat would be "hard-coding a specific type"), but not IBeing b1 = cache[1] (because it wouldn't allow "interesting uses" of b1 such as accessing b1.IBInstance ). I still don't think that can be done (at least within the constraints given), but maybe that isn't what you meant.
modified 27-Oct-20 7:03am.
|
|
|
|
|
Hi, Harold, thanks for responding !
I'm just groping the elephant in the dark room hoping to become wiser ... with one usable eye, I'm hallway to getting the "blindness" part down
Do you think the run-time "rehydration" from cast-to-interface back to instance is inherently a reflective process ? Perhaps this kind of hocus-pocus is just bootlegging Dynamic >
Perhaps one of our IL gurus like @Richard-MacCutchan or @RichardDeeming can enlighten us on the internal structure of such entities.
cheers, Bill
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
modified 27-Oct-20 16:49pm.
|
|
|
|
|
Hi,
I have tried the following code to restrict input to numbers. But, I have used calcEngin library for doing mathematical calculation in that textBox, so I need to allow "()+-*/" characters too.
How can I allow those special characters?
private void textBoxTT_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit(e.KeyChar))
e.Handled = true;
return;
}
|
|
|
|
|
|
Can you please guide me more? I couldn't understand how to solve my issue.
|
|
|
|
|
Look at the other methods to see which one(s) can provide the checks that you need.
|
|
|
|
|
for cases where you must handle entry of groups of characters that do not map to the many
Is---- methods provided by Char, you may need to test if the char is in a specific group of characters:
private string legalChars = "()+-*/";
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
char c = e.KeyChar;
e.Handled = !
(
char.IsDigit(c)
|| legalChars.Contains(c)
);
}
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|
|
At the moment the program will only reveal a letter if the users input matches the specified letter within the iteration.
What I would like to do is reveal a letter despite what iteration the user is on...e.g. if the user inputs "P" on the first iteration I want the program to reveal all the Ps" in happy.
Thanks!
{
string[] secret = { "h", "a", "p", "p", "y" };
string[] hidden = { "_", "_", "_", "_", "_" };
string letter = "";
Console.WriteLine("Welcome to guess a word game");
for (int i = 0; i < secret.Length; i++)
{
Console.WriteLine("Guess a letter: ");
letter = Console.ReadLine();
if (secret[i] == letter)
{
hidden[i] = letter;
}
foreach (string k in hidden)
{
Console.Write(k.ToString());
}
Console.WriteLine();
}
Console.WriteLine();
if(secret == hidden)
{
Console.WriteLine("You have guessed the correct word!");
}
else
{
Console.WriteLine("unfortunately you have not gussed the correct word");
}
Console.ReadLine();
}
}
}
|
|
|
|
|
some suggestions:
1 use Console.ReadKey() to read a single character at a time: [^]
you can convert the result of ReadKey to a Char or String like this:
ConsoleKeyInfo ckey = Console.ReadKey();
char chr = ckey.KeyChar;
string str = chr.ToString(); 2 you will need to use a loop, like a while loop that lets the user nake attempts:
while (true)
{
Console.WriteLine(hidden);
Console.Write("? ");
ckey = Console.ReadKey();
char chr = ckey.KeyChar;
string str = chr.ToString();
if (secret.Contains(chr))
{
for (int i = 0; i < secret.Length; i++)
{
if (secret[i].Equals(chr))
{
}
}
}
Console.WriteLine();
if (hidden == secret || ckey.Key == ConsoleKey.Escape)
{
Console.WriteLine(hidden);
break;
}
} Hint: use a StringBuilder
«One day it will have to be officially admitted that what we have christened reality is an even greater illusion than the world of dreams.» Salvador Dali
|
|
|
|