How can I prevent outside code to manipulate contents of the Dictionary? - c#-3.0

I want a Dictionary<string, string> property which should not be changed/set by the outside code. To achieve this, I can declare private variable and it's property with get accessor only.
e.g.
private static Dictionary<string, string> myDic = new Dictionary <string, string>();
Public static Dictionary<string, string> MyDictionary
{
get { return myDic;}
}
But in this case, outside code can manipulate 'contents' of the dictionary.
e.g. MYClass.MyDictionary["FirstSampleKey"] = "Replacing original value by New Value";
I dont want any outside code to manipulate contents of the dictionary. How can I achieve this?

I don't believe there is a read only dictionary (which would be nice as there is a ReadOnlyCollection). Your best bet would probably be to not expose the dictionary at all and expose properties/methods that allow the developer to get at the information without allowing them to directly access the dictionary.
If this is something you will be doing a lot of, you can look into either using someone else's ReadOnlyDictionary implementation (there are plenty out there if you Google it), or you can write your own.

I would also say that you could write a method for the developers to look up their words, or else you could return a copy of the dictionary, this way the dictionary works as it do now, but of cause you would have to copy the dictionary every time the get method is called which could take some time if it's a large dictionary.

Related

How to make copy of array's elements in the dart

Getting wired issue like main array has been changed if changed value of another array. I think issue is about copying same address, not sure but just thinking of it. I have tried from last 3 hours but unable to get rid from it.
Look at below illustration to get better idea.
List<page> _pageList;
List<page> _orderList = [];
_pageList = _apiResponse.result as List<page>;
_orderList.add(_pageList[0].element);
_orderList[0].title = "XYZ"
//--> Here if I change the `_orderList[0].title` then it also change the `title` inside "_pageList"
How can we prevent the changes in main array?
I got same issue in my one of the project. What I have done is, use json to encode and decode object that help you to make copy of the object so that will not be affected to the main List.
After 3rd line of your code, make changes like below
Elements copyObject = Elements.fromJson(_pageList[0].element.toJson());
// First of all you have to convert your object to the Map and and map to original object like above
_orderList.add(copyObject);
Hope that will help you.
You can use a getter function to create a copy of your list and use that instead of
altering your actual list.
example:
List<Page> get orderList{
return [..._orderList];
}
Lists in Dart store references for complex types, so this is intended behaviour.
From your code:
_orderList.add(_pageList[0].element);
_orderList[0] and _pageList[0].element point to the same reference (if they are non-primitive).
There is no general copy() or clone() method in dart, as far as i know. So you need to copy the object yourself, if you want a separate instance. (see this question)

Best place to put server private keys on Xcode project

i'm coding an app with server API calls and I've got a private key for access, my question is: Where should I put that key? Let me explain a little more.
When we work for example in JavaScript we have a .env file, it contains sensitive content and is in most of cases on .gitignore file, so where is a correct place to save and access to those private keys on Xcode? or is correct simply to do something like:
let key = "MY_KEY"
thanks in advance
Even though what Codey said is correct but its much better to use a struct and create variables inside that struct. Simply making a variable 'key' might become troublesome in future as you might end up redeclaring it and losing everything. Also by using a struct, it gives much more clarity for the developer, it would make your code much more understandable.
Instead of going through that trouble do this.
Create a new swift file. Name is something like GlobalVariables.swift (or as Codey said).
Now create a struct inside that file.
struct serverInfo
{
static let key = "KEY"
static let server = "0.0.0.0"
}
You can access these variables anywhere on the program with
let x = serverInfo.key
let y = serverInfo.server
If this is only for development purposes, then you can store your password in the code. But note, that this file shouldn't be uploaded to your repository.
I would suggest to create a separate file (like Config.swift) and write your global configuration constants in this file.
// Config.swift
//
let key = "MY_KEY"
let server = "10.0.0.1"
You can then access these variables everywhere in your project. So this is the file you don't want to commit. Keep in mind, that everyone that uses your project needs such a file in order for the project to compile.

Options to storing data in a prefab

After realizing that you can't really use UnityEvents in Scriptable Objects (they don't read global variable values correctly). I had to move to another solution for where to store my Dialogs.
The best solution I could find was to just store them in the corresponding NPC-prefab. This is really convenient. However this leaves a bad taste in my mouth, it just feels wrong to store data in a prefab like this. Is it a bad practice?
For example if I were to refactor something in the DialogObject, everything would be lost.
Since I can't seem to successfully store UnityEvents anywhere (can't serialize them as Json and as mentioned Scriptable Objects don't seem to handle them well) I feel like this is the only solution if I want to be able to use the Editor to create Dialogs.
Just checking here first, is this stupid? is there another way?
I am trying to save a List of this:
[System.Serializable]
public class DialogObject {
public List<PageData> conversations = new List<PageData>();
public UnityEvent postEvent; //Invoked on last page of Dialog
}
I would say yes, prefabs are meant to be a template to create new items of a type. You are trying to save data states.
Even though you cannot serialize the UnityEvent, you could serialize its content.
If you assign via inspector, you can use https://docs.unity3d.com/ScriptReference/Events.UnityEventBase.GetPersistentMethodName.html
But then you would not have problem of storage if you know from the start where it goes.
Second solution is when you assign the method to the UnityEvent, store it.
void AddListener (UnityAction ev)
{
MethodInfo mi = ev.Method;
// Use mi
postEvent.AddListener(ev);
}
With the mi reference, you have the name of the method, its type, the object it belongs to and anything you need.

Iterate over properties of an object (in Realm, or maybe not)

I'm working on a project that uses Realm for the database (that will come into the picture later). I've just discovered key-value coding and I want to use it in converting a TSV table into object properties (using the column headers from the table as the keys). Right now it looks like this:
let mirror = Mirror(reflecting: newSong)
for property in mirror.children {
if let index = headers.index(of: property.label!) {
newSong.setValue(headers[index], forKey: property.label!)
} else {
propertiesWithoutHeaders.append(property.label!)
}
}
Is there a way to iterate over properties without a mirror? I really could have sworn that I read in the Realm documentation (or maybe even in Apple's KVC documentation) that you can do something like for property in Song.properties or for property in Song.self.properties to achieve the same thing.
Besides it being a little more efficient, the main reason I want to do this is because in the same place I think I read this, I think they said that the iterating (or the KVC?) only works with Strings, Ints, Bools and Dates, so it would automatically skip the properties that are Objects (since you can't set them with in the same way). The above code is actually a simplification of my code, in the actual version I'm currently skipping over the Objects like this:
let propertiesToSkip = ["title", "artist", "genre"]
for property in mirror.children where !propertiesToSkip.contains(property.label!) {
...
Did I imagine this .properties thing? Or, is there a way to iterate in this way, automatically skipping over Objects/Classes without having to name them as I do above?
Thanks :)
No you didn't imagine it. :)
Realm exposes the schema encompassing the properties of each type of model in a database in two places: in the parent Realm instance, or in an Object itself.
In the Realm instance:
// Get an instance of the Realm object
let realm = try! Realm()
// Get the object schema for just the Mirror class. This contains the property names
let mirrorSchema = realm.schema["Mirror"]
// Iterate through each property and print its name
for property in mirrorSchema.properties {
print(property.name)
}
Realm Object instances expose the schema for that object via the Object.objectSchema property.
Check out the schema property of Realm in the Realm Swift Documentation for more information on what kind of data you can get out of the schema properties. :)

Class design: file conversion logic and class design

This is pretty basic, but sort of a generic issue so I want to hear what people's thoughts are. I have a situation where I need to take an existing MSI file and update it with a few standard modifications and spit out a new MSI file (duplication of old file with changes).
I started writing this with a few public methods and a basic input path for the original MSI. The thing is, for this to work properly, a strict path of calls has to be followed from the caller:
var custom = CustomPackage(sourcemsipath);
custom.Duplicate(targetmsipath);
custom.Upgrade();
custom.Save();
custom.WriteSmsXmlFile(targetxmlpath);
Would it be better to put all the conversion logic as part of the constructor instead of making them available as public methods? (in order to avoid having the caller have to know what the "proper order" is):
var custom = CustomPackage(sourcemsipath, targetmsipath); // saves converted msi
custom.WriteSmsXmlFile(targetxmlpath); // saves optional xml for sms
The constructor would then directly duplicate the MSI file, upgrade it and save it to the target location. The "WriteSmsXmlFile is still a public method since it is not always required.
Personally I don't like to have the constructor actually "do stuff" - I prefer to be able to call public methods, but it seems wrong to assume that the caller should know the proper order of calls?
An alternative would be to duplicate the file first, and then pass the duplicated file to the constructor - but it seems better to have the class do this on its own.
Maybe I got it all backwards and need two classes instead: SourcePackage, TargetPackage and pass the SourcePackage into the constructor of the TargetPackage?
I'd go with your first thought: put all of the conversion logic into one place. No reason to expose that sequence to users.
Incidentally, I agree with you about not putting actions into a constructor. I'd probably not do this in the constructor, and instead do it in a separate converter method, but that's personal taste.
It may be just me, but the thought of a constructor doing all these things makes me shiver. But why not provide a static method, which does all this:
public class CustomPackage
{
private CustomPackage(String sourcePath)
{
...
}
public static CustomPackage Create(String sourcePath, String targetPath)
{
var custom = CustomPackage(sourcePath);
custom.Duplicate(targetPath);
custom.Upgrade();
custom.Save();
return custom;
}
}
The actual advantage of this method is, that you won't have to give out an instance of CustomPackage unless the conversion process actually succeeded (safe of the optional parts).
Edit In C#, this factory method can even be used (by using delegates) as a "true" factory according to the Factory Pattern:
public interface ICustomizedPackage
{
...
}
public class CustomPackage: ICustomizedPackage
{
...
}
public class Consumer
{
public delegate ICustomizedPackage Factory(String,String);
private Factory factory;
public Consumer(Factory factory)
{
this.factory = factory;
}
private ICustomizedPackage CreatePackage()
{
return factory.Invoke(..., ...);
}
...
}
and later:
new Consumer(CustomPackage.Create);
You're right to think that the constructor shouldn't do any more work than to simply initialize the object.
Sounds to me like what you need is a Convert(targetmsipath) function that wraps the calls to Duplicate, Upgrade and Save, thereby removing the need for the caller to know the correct order of operations, while at the same time keeping the logic out of the constructor.
You can also overload it to include a targetxmlpath parameter that, when supplied, also calls the WriteSmsXmlFile function. That way all the related operations are called from the same function on the caller's side and the order of operations is always correct.
In such situations I typicaly use the following design:
var task = new Task(src, dst); // required params goes to constructor
task.Progress = ProgressHandler; // optional params setup
task.Run();
I think there are service-oriented ways and object-oritented ways.
The service-oriented way would be to create series of filters that passes along an immutable data transfer object (entity).
var service1 = new Msi1Service();
var msi1 = service1.ReadFromFile(sourceMsiPath);
var service2 = new MsiCustomService();
var msi2 = service2.Convert(msi1);
service2.WriteToFile(msi2, targetMsiPath);
service2.WriteSmsXmlFile(msi2, targetXmlPath);
The object-oriented ways can use decorator pattern.
var decoratedMsi = new CustomMsiDecorator(new MsiFile(sourceMsiPath));
decoratedMsi.WriteToFile(targetMsiPath);
decoratedMsi.WriteSmsXmlFile(targetXmlPath);